1. 程式人生 > >kobject_uevent,uevent_helper,/sys/kernel/uevent_helper,/proc/sys/kernel/hotplug

kobject_uevent,uevent_helper,/sys/kernel/uevent_helper,/proc/sys/kernel/hotplug

class_device_create
	class_device_register
		class_device_add
			kobject_uevent(&class_dev->kobj, KOBJ_ADD);
				kobject_uevent_env
					action_string = action_to_string(action);

					uevent_ops->filter
					subsystem = uevent_ops->name(kset, kobj);

					envp = kzalloc(NUM_ENVP * sizeof (char *), GFP_KERNEL);
					buffer = kmalloc(BUFFER_SIZE, GFP_KERNEL);
					
					devpath = kobject_get_path(kobj, GFP_KERNEL);
					
					envp[i++] = "HOME=/";...
					
					#if defined(CONFIG_NET)
					/* send netlink message */
					
					if (uevent_helper[0]) {
						char *argv [3];

						argv [0] = uevent_helper;
						argv [1] = (char *)subsystem;
						argv [2] = NULL;
						call_usermodehelper (argv[0], argv, envp, 0);
					}

關於uevent_helper(在Source Insight中搜索)
1.對/sys/kernel/uevent_helper 檔案的讀寫就是對uevent_helper的讀寫
	linux/kernel/ksysfs.c
	
static ssize_t uevent_helper_show(struct kset *kset, char *page)
{
	return sprintf(page, "%s\n", uevent_helper);
}
static ssize_t uevent_helper_store(struct kset *kset, const char *page, size_t count)
{
	if (count+1 > UEVENT_HELPER_PATH_LEN)
		return -ENOENT;
	memcpy(uevent_helper, page, count);
	uevent_helper[count] = '\0';
	if (count && uevent_helper[count-1] == '\n')
		uevent_helper[count-1] = '\0';
	return count;
}

KERNEL_ATTR_RW(uevent_helper);//宣告一個subsys_attribute變數 uevent_helper_attr
				//它對應sysfs 中的一個檔案,檔名是uevent_helper
				//它的讀寫函式分別是uevent_helper_show,uevent_helper_store
	#define KERNEL_ATTR_RW(_name) \
		static struct subsys_attribute _name##_attr = __ATTR(_name, 0644, _name##_show, _name##_store)
			#define __ATTR(_name,_mode,_show,_store) { \
				.attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE },	\
				.show	= _show,					\
				.store	= _store,					\
			}

int error = subsystem_register(&kernel_subsys);//註冊子系統
	//kernel_subsys的建立使用decl_subsys巨集
	decl_subsys(kernel, NULL, NULL);//建立了/sys/kernel目錄

error = sysfs_create_group(&kernel_subsys.kobj,&kernel_attr_group);//在子系統中建立一組檔案
	static struct attribute_group kernel_attr_group = {
		.attrs = kernel_attrs,
	};
		
		static struct attribute * kernel_attrs[] = {
			#if defined(CONFIG_HOTPLUG) && defined(CONFIG_NET)
			&uevent_seqnum_attr.attr,
			&uevent_helper_attr.attr,//uevent_helper檔案
			#endif
			#ifdef CONFIG_KEXEC
			&kexec_loaded_attr.attr,
			&kexec_crash_loaded_attr.attr,
			#endif
			NULL
		};



2.對/proc/sys/kernel/hotplug 檔案的讀寫就是對uevent_helper的讀寫
	/linux/kernel/sysctl.c
	#if defined(CONFIG_HOTPLUG) && defined(CONFIG_NET)
	{
		.ctl_name	= KERN_HOTPLUG,
		.procname	= "hotplug",//建立/proc/sys/kernel/hotplug檔案
		.data		= &uevent_helper,//對檔案讀寫的資料物件,讀寫/proc/sys/kernel/hotplug就是對uevent_helper的讀寫
		.maxlen		= UEVENT_HELPER_PATH_LEN,
		.mode		= 0644,
		.proc_handler	= &proc_dostring,
		.strategy	= &sysctl_string,
	},

	

	所以,在使用mdev時,在/etc/init.d/rc.S 寫入 echo "/sbin/mdev" > /proc/sys/kernel/hotplug
					和 寫入 echo "/sbin/mdev" > /sys/kernel/uevent_helper作用應該是相同的