事情是如何发生的?
当按下开机键后,电脑经过自检,执行引导程序,内核初始化,然后创建了内核线程init线程,init线程调用do_basic_setup()来初始化外部设备,加载驱动程序.... (这一段实在其他地方看来的,并不表示我看过内核初始化的代码)
- static void __init do_basic_setup(void)
- {
- init_workqueues();
- cpuset_init_smp();
- usermodehelper_init();
- init_tmpfs();
- driver_init(); /* 初始化设备 */
- init_irq_proc;
- do_ctors();
- do_initcalls();
- }
下面是driver_init()函数
- void __init driver_init(void)
- {
- /* These are the core pieces */
- devtmpfs_init();
- devices_init(); /* 设备初始化 */
- buses_init(); /* 总线初始化 */
- classes_init(); /* 类初始化 */
- firmware_init();
- hypervisor_init();
- /* These are also core pieces, but must come after the
- * core core pieces.
- */
- platform_bus_init();
- system_bus_init();
- cpu_dev_init();
- memory_dev_init();
- }
它又调用了devices_init()、buses_init()、chasses_init();
下面是devices_init()
- int __init devices_init(void)
- {
- /* 创建/sys/devices目录 和 devices_kset */
- devices_kset = kset_create_and_add("devices", &device_uevent_ops, NULL);
- if (!devices_kset)
- return -ENOMEM;
- /* 创建/sys/dev目录 和 dev_kobj */
- dev_kobj = kobject_create_and_add("dev", NULL);
- if (!dev_kobj)
- goto dev_kobj_err;
- /* 创建/sys/dev/block目录 和sysfs_dev_block_kobj */
- sysfs_dev_block_kobj = kobject_create_and_add("block", dev_kobj);
- if (!sysfs_dev_block_kobj)
- goto block_kobj_err;
- /* 创建/sys/dev/char目录 和 sysfs_dev_char_kobj */
- sysfs_dev_char_kobj = kobject_create_and_add("char", dev_kobj);
- if (!sysfs_dev_char_kobj)
- goto char_kobj_err;
- return 0;
- char_kobj_err:
- kobject_put(sysfs_dev_block_kobj);
- block_kobj_err:
- kobject_put(dev_kobj);
- dev_kobj_err:
- kset_unregister(devices_kset);
- return -ENOMEM;
- }
因此devices_init()就是调用kset_create_and_add和kobject_create_and_add函数来创建kset和kobject对象。
devices_kset = kset_create_and_add("devices", &device_uevent_ops, NULL);
dev_kobj = kobject_create_and_add("dev", NULL);
sysfs_dev_block_kobj = kobject_create_and_add("block", dev_kobj);
sysfs_dev_char_kobj = kobject_create_and_add("char", dev_kobj);
下面的buses_init,classes_init,firmware_init,hypervisor_init与此类似,下面列出这些函数创建的kset和kobject对象。在创建这些对象的时候也会在/sys目录下创建相应的目录。
- buses_init:
- bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL);
- classes_init:
- class_kset = kset_create_and_add("class", NULL, NULL);
- firmware_init:
- firmware_kobj = kobject_create_and_add("firmware", NULL);
- hypervisor_init:
- hypervisor_kobj = kobject_create_and_add("hypervisor", NULL);
接着是函数:platform_bus_init(),
- int __init platform_bus_init(void)
- {
- int error;
- early_platform_cleanup();
- /* 注册了platform_bus, 即在/sys/devices目录下创建了platform目录,以及目录下的相关属性文件*/
- error = device_register(&platform_bus);
- if(error) return error;
- /* 注册platform_bus_type, 在/sys/bus/目录下创建了platform目录,及相应的属性文件 */
- error = bus_register(&platform_bus_type);
- if(error) device_unregister(&platform_bus);
- return error;
- }
-
- /* platform_bus的定义 */
- struct device platform_bus = {
- .init_name = "platform",
- };
-
- /* platform_bus_type的定义 */
- struct bus_type platform_bus_type = {
- .name = "platform",
- .dev_attrs = platform_dev_attrs,
- .match = platform_match,
- .uevent = platform_uevent,
- .pm = &platform_dev_pm_ops
- };
接着是:system_bus_init();
该函数创建了system_kset,以及/sys/devices下的system目录:
接着是:cpu_dev_init();
- int __init cpu_dev_init(void)
- {
- int err;
- /* 见下面 */
- err = sysdev_class_register(&cpu_sysdev_class);
- if (!err)
- /* 调用了sysdev_class_create_file(&cpu_sysdev_class, []);
- 为数组cpu_state_attr中的属性创建文件,即创建了online, possible, present, kernel_max,offline .
- 读这些文件时会调用相应的函数:print_cpus_online, print_cpus_kernel_max, print_cpus_onlinetype, print_cpus_possibletype, print_cpus_presenttype */
- err = cpu_states_init();
- #if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT)
- if (!err)
- err = sched_create_sysfs_power_savings_entries(&cpu_sysdev_class);
- #endif
- return err;
- }
-
- struct sysdev_class cpu_sysdev_class = {
- .name = "cpu",
- };
- struct sysdev_class {
- const char *name;
- struct list_head drivers;
- /* Default operations for these types of devices */
- int (*shutdown)(struct sys_device *);
- int (*suspend)(struct sys_device *, pm_message_t state);
- int (*resume)(struct sys_device *);
- struct kset kset;
- };
这里的sysdev_class结构体类似与bus_type和device。
在system_bus_init函数创建了system_kset,
下面是sysdev_class_register()函数
- int sysdev_class_register(struct sysdev_class *cls)
- {
- ...
- INIT_LIST_HEAD(&cls->drivers);
- memset(&cls->kset.kobj, 0x00, sizeof(struct kobject));
- cls->kset.kobj.parent = &system_kset->kobj;
- cls->kset.kobj.ktype = &ktype_sysdev_class;
- cls->kset.kobj.kset = system_kset;
- retval = kobject_set_name(&cls->kset.kobj, "%s", cls->name);
- ...
- return kset_register(&cls->kset);
- }
可见这里就是将cpu_sysdev_class加入到设备模型中去,该对象的父kset为system_kset,ktype为ktype_sysdev_class。
因此在/sys/devices/system目录下创建了cpu目录
最后是memory_dev_init函数
简单看下该函数就知道这个和上面的cpu_dev_init是类似的。
- int __init memory_dev_init(void)
- {
- unsigned int i;
- int ret;
- int err;
- memory_sysdev_class.kset.uevent_ops = &memory_uevent_ops;
- ret = sysdev_class_register(&memory_sysdev_class);
- if (ret)
- goto out;
- /*
- * Create entries for memory sections that were found
- * during boot and have been initialized
- */
- for (i = 0; i < NR_MEM_SECTIONS; i++) {
- if (!present_section_nr(i))
- continue;
- err = add_memory_block(0, __nr_to_section(i), MEM_ONLINE,
- 0, BOOT);
- if (!ret)
- ret = err;
- }
- err = memory_probe_init();
- if (!ret)
- ret = err;
- err = block_size_init();
- if (!ret)
- ret = err;
- out:
- if (ret)
- printk(KERN_ERR "%s() failed: %d\n", __func__, ret);
- return ret;
- }
(非常奇怪,在我的ubuntu 10.10上竟然没有找到/sys/device/system/memory目录,内核版本是2.6.35-32-generic, x86,不该呀,有人知道原因吗?)
可以看出整个driver_init()只是在/sys下创建了一系列的kset和kobject对象和相应的目录,但没有创建任何真正的设备,或者虚拟的设备。比如/sys/devices/system/cpu目录下的cpu0目录的创建,这些可能是在do_initcalls中处理的,我得先搞清楚这个函数是怎么起作用的。
阅读(274) | 评论(0) | 转发(0) |