原文地址:http://blog.chinaunix.net/uid-24631445-id-3419097.html
事情是如何发生的?
当按下开机键后,电脑经过自检,执行引导程序,内核初始化,然后创建了内核线程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中处理的,我得先搞清楚这个函数是怎么起作用的。
阅读(757) | 评论(0) | 转发(0) |