1. 程式人生 > 其它 >kobject: '(null)' (00000000bbe09fa2): is not initialized, yet kobject_put() is being called.

kobject: '(null)' (00000000bbe09fa2): is not initialized, yet kobject_put() is being called.

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