1. 问题说明
在学习宋宝华老师第六章 "字符设备驱动" 示例时,卸载globalmem
模块会报告下述异常:
[ 4039.481628] ------------[ cut here ]------------
[ 4039.482450] kobject: '(null)' (00000000bbe09fa2): is not initialized, yet kobject_put() is being called.
[ 4039.483446] WARNING: CPU: 5 PID: 7475 at lib/kobject.c:750 kobject_put+0x74/0x90
[ 4039.484247] Modules linked in: globalmem(O-) [last unloaded: globalmem]
[ 4039.484700] CPU: 5 PID: 7475 Comm: rmmod Tainted: G B W O 5.10.74.3-microsoft-standard-WSL2 #5
[ 4039.485330] RIP: 0010:kobject_put+0x74/0x90
[ 4039.485604] Code: 85 c0 7e 2b 5b 5d 41 5c 41 5d 41 5e 41 5f c3 48 89 ef e8 6f 7a 73 ff 48 8b 75 00 48 89 ea 48 c7 c7 c0 4e ea 9f e8 c5 1c 92 00 <0f> 0b eb b1 c3 5b 4c 89 e7 be 03 00 00 00 5d 41 5c 41 5d 41 5e 41
[ 4039.486863] RSP: 0018:ffff88813f7e7e18 EFLAGS: 00010282
[ 4039.487235] RAX: 0000000000000000 RBX: 00000000ffffffff RCX: 0000000000000000
[ 4039.487774] RDX: dffffc0000000000 RSI: 0000000000000008 RDI: ffffed1027efcfb5
[ 4039.488321] RBP: ffff8881343d4000 R08: 0000000000000000 R09: ffffed1027efcf54
[ 4039.488883] R10: ffff88813f7e7a9f R11: ffffed1027efcf53 R12: 0000000000000000
[ 4039.489501] R13: ffff8881343d403c R14: 0000000000000800 R15: 0000000000000000
[ 4039.490175] FS: 00007fb3dfaf5540(0000) GS:ffff888366b40000(0000) knlGS:0000000000000000
[ 4039.490874] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 4039.491391] CR2: 00007fb3dfcbe421 CR3: 000000017206e000 CR4: 0000000000350ea0
[ 4039.491994] Call Trace:
[ 4039.492193] globalmem_exit+0x18/0x50 [globalmem]
[ 4039.492560] __x64_sys_delete_module+0x22a/0x300
[ 4039.492955] ? __ia32_sys_delete_module+0x300/0x300
[ 4039.493360] ? mem_cgroup_handle_over_high+0x2b/0x360
[ 4039.493762] ? exit_to_user_mode_prepare+0xc1/0xe0
[ 4039.494240] do_syscall_64+0x33/0x80
[ 4039.494575] entry_SYSCALL_64_after_hwframe+0x44/0xa9
[ 4039.494955] RIP: 0033:0x7fb3dfc41bcb
[ 4039.495233] Code: 73 01 c3 48 8b 0d c5 82 0c 00 f7 d8 64 89 01 48 83 c8 ff c3 66 2e 0f 1f 84 00 00 00 00 00 90 f3 0f 1e fa b8 b0 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 95 82 0c 00 f7 d8 64 89 01 48
[ 4039.496755] RSP: 002b:00007ffc444400b8 EFLAGS: 00000206 ORIG_RAX: 00000000000000b0
[ 4039.497470] RAX: ffffffffffffffda RBX: 00005591f7a3d790 RCX: 00007fb3dfc41bcb
[ 4039.498129] RDX: 000000000000000a RSI: 0000000000000800 RDI: 00005591f7a3d7f8
[ 4039.498714] RBP: 00007ffc44440118 R08: 0000000000000000 R09: 0000000000000000
[ 4039.499272] R10: 00007fb3dfcbdac0 R11: 0000000000000206 R12: 00007ffc444402f0
[ 4039.499818] R13: 00007ffc444418da R14: 00005591f7a3c2a0 R15: 00005591f7a3d790
[ 4039.500364] ---[ end trace 526b84e5b448dd54 ]---
2. 问题分析
查看对应版本的内核代码,发现问题出在通过cdev_del
接口删除字符设备时,内核对未初始化就释放的对象报告了一个warning。
// fs/char_dev.c
void cdev_del(struct cdev *p)
{
cdev_unmap(p->dev, p->count);
kobject_put(&p->kobj);
}
// lib/kobject.c
void kobject_put(struct kobject *kobj)
{
if (kobj) {
if (!kobj->state_initialized)
WARN(1, KERN_WARNING
"kobject: '%s' (%p): is not initialized, yet kobject_put() is being called.\n",
kobject_name(kobj), kobj);
kref_put(&kobj->kref, kobject_release);
}
}
EXPORT_SYMBOL(kobject_put);
3. 解决办法
既然是未初始化导致的warning
,那么我们将其初始化即可。
// globalmem.c
static int __init globalmem_init(void)
{
int ret;
dev_t devno = MKDEV(globalmem_major, 0);
if (globalmem_major)
ret = register_chrdev_region(devno, 1, "globalmem");
else {
ret = alloc_chrdev_region(&devno, 0, 1, "globalmem");
globalmem_major = MAJOR(devno);
}
if (ret < 0)
return ret;
globalmem_devp = kzalloc(sizeof(struct globalmem_dev), GFP_KERNEL);
if (!globalmem_devp) {
printk(KERN_ERR "kzalloc failed!\n");
ret = -ENOMEM;
goto fail_malloc;
}
// 这里对cdev对象进行初始化即可
cdev_init(&globalmem_devp->cdev, &globalmem_fops);
globalmem_setup_cdev(globalmem_devp, 0);
return 0;
fail_malloc:
unregister_chrdev_region(devno, 1);
return ret;
}
4. 测试验证
➜ ch06 sudo dmesg -c
➜ ch06 make
make -C /lib/modules/5.10.74.3-microsoft-standard-WSL2/build M=/home/dw/src/drivers/study/globalmem/ch06 modules
make[1]: Entering directory '/home/dw/src/kernel/WSL2-Linux-Kernel'
make[1]: Leaving directory '/home/dw/src/kernel/WSL2-Linux-Kernel'
➜ ch06 sudo insmod ./globalmem.ko
➜ ch06 sudo rmmod globalmem
➜ ch06 dmesg
[ 4464.318048] kobject: 'globalmem' (00000000481400b3): kobject_add_internal: parent: 'module', set: 'module'
[ 4464.319001] kobject: 'holders' (0000000061e89e87): kobject_add_internal: parent: 'globalmem', set: '<NULL>'
[ 4464.319864] kobject: 'notes' (000000001486d8de): kobject_add_internal: parent: 'globalmem', set: '<NULL>'
[ 4464.320518] kobject: 'globalmem' (00000000481400b3): kobject_uevent_env
[ 4464.320965] kobject: 'globalmem' (00000000481400b3): fill_kobj_path: path = '/module/globalmem'
[ 4473.702248] try to del cdev
[ 4473.702258] kobject: '(null)' (00000000e357b512): kobject_cleanup, parent 0000000000000000
[ 4473.703282] kobject: '(null)' (00000000e357b512): calling ktype release
[ 4473.703858] try to free globalmem_devp
[ 4473.703862] try to unregister_chrdev_region
[ 4473.704335] kobject: 'holders' (0000000061e89e87): kobject_cleanup, parent 00000000481400b3
[ 4473.705287] kobject: 'holders' (0000000061e89e87): auto cleanup kobject_del
[ 4473.705756] kobject: 'holders' (0000000061e89e87): calling ktype release
[ 4473.706250] kobject: (0000000061e89e87): dynamic_kobj_release
[ 4473.706703] kobject: 'holders': free name
[ 4473.706984] kobject: 'notes' (000000001486d8de): kobject_cleanup, parent 00000000481400b3
[ 4473.707543] kobject: 'notes' (000000001486d8de): auto cleanup kobject_del
[ 4473.708034] kobject: 'notes' (000000001486d8de): calling ktype release
[ 4473.708514] kobject: (000000001486d8de): dynamic_kobj_release
[ 4473.709012] kobject: 'notes': free name
[ 4473.709495] kobject: 'globalmem' (00000000481400b3): kobject_cleanup, parent 000000000152e7cb
[ 4473.710273] kobject: 'globalmem' (00000000481400b3): auto cleanup kobject_del
[ 4473.710862] kobject: 'globalmem' (00000000481400b3): auto cleanup 'remove' event
[ 4473.711393] kobject: 'globalmem' (00000000481400b3): kobject_uevent_env
[ 4473.711862] kobject: 'globalmem' (00000000481400b3): fill_kobj_path: path = '/module/globalmem'
[ 4473.712499] kobject: 'globalmem' (00000000481400b3): calling ktype release
[ 4473.712937] kobject: 'globalmem': free name