Coder
分类: LINUX
2010-08-08 19:19:54
还是从那个无比复杂的start_kernel()函数开始,来看看是如何一步步执行到了我们的初始化Driver
Model的函数的。在start_kernel()初始化系统即将结束,通往新世界的大门就要打开的的时候,调用了rest_init()函数(init/main.c)。在rest_init()函数中,创建了一个内核线程,用以执行一个名为kernel_init()的函数(init/main.c)。而在这个kernel_init()函数中,则又调用了do_basic_setup()函数(init/main.c)。而正是在这个do_basic_setup()函数中,我们终于找到了那个我们苦苦寻觅的初始化Driver
Model的函数driver_init()。(在这个do_basic_setup()函数的最后,也调用do_initcalls()函数)。
接下来让我们一探Driver Model初始化的究竟。我们的目标,要将sysfs文件系统的层次结构,和Driver Model中这一个个复杂的数据结构之间的关系搞搞清楚。首先,想想此时此刻,系统初始化完成了些什么了:初始化虚拟文件系统的vfs_caches_init_early()和vfs_caches_init(totalram_pages)早都已经执行完了,虚拟文件系统所用的各种对象的slab缓冲这个时候早都已经初始化好了,他们已经在枕戈待旦,随时准备着听候召唤呢。在vfs_caches_init()函数中也调用了mnt_init()、bdev_cache_init()和chrdev_init()而挂载了根文件系统,挂载了sysfs文件系统,初始化了字符设备子系统和块设备子系统。但是实际根文件系统的挂载还没有开始。我们来看下这个神秘的driver_init()函数的定义:
---------------------------------------------------------------------
drivers/base/init.c
14
/**
15 *
driver_init - initialize driver model.
16 *
17 *
Call the driver model init functions to initialize their
18 *
subsystems. Called early from init/main.c.
19 */
20 void __init driver_init(void)
21 {
22
/* These are the core pieces */
23
devtmpfs_init();
24
devices_init();
25
buses_init();
26
classes_init();
27
firmware_init();
28
hypervisor_init();
29
30
/* These are also core pieces, but must come after the
31
* core core pieces.
32
*/
33
platform_bus_init();
34
system_bus_init();
35
cpu_dev_init();
36
memory_dev_init();
37 }
---------------------------------------------------------------------
这个函数看上去倒是挺简洁的,区区几行十几行而已,即使是把关于这个函数的注释也加上,也都还不到30行。只是在这个函数看似温和平静的外表下则又实在是暗藏玄机。因为每一个函数都不是省油的灯,好惹的主啊。
1、调用devtmpfs_init()来创建devtmpfs实例,driver-core设备将会在这个文件系统中创建设备节点。来看下它的定义:
---------------------------------------------------------------------
drivers/base/devtmpfs.c
45
static int dev_get_sb(struct file_system_type *fs_type, int flags,
46 const char *dev_name,
void *data, struct vfsmount *mnt)
47 {
48
return get_sb_single(fs_type, flags, data, shmem_fill_super, mnt);
49 }
50
51 static struct file_system_type dev_fs_type
= {
52
.name = "devtmpfs",
53
.get_sb = dev_get_sb,
54
.kill_sb = kill_litter_super,
55 };
363
/*
364 * Create devtmpfs instance, driver-core
devices will add their
365 * device nodes here.
366 */
367
int __init devtmpfs_init(void)
368
{
369 int err;
370 struct vfsmount *mnt;
371 char options[] = "mode=0755";
372
373 err =
register_filesystem(&dev_fs_type);
374 if (err) {
375 printk(KERN_ERR "devtmpfs:
unable to register devtmpfs "
376 "type %i\n",
err);
377 return err;
378 }
379
380 mnt = kern_mount_data(&dev_fs_type,
options);
381 if (IS_ERR(mnt)) {
382 err = PTR_ERR(mnt);
383 printk(KERN_ERR "devtmpfs: unable
to create devtmpfs %i\n", err);
384
unregister_filesystem(&dev_fs_type);
385 return err;
386 }
387 dev_mnt = mnt;
388
389 printk(KERN_INFO "devtmpfs:
initialized\n");
390 return 0;
391
}
---------------------------------------------------------------------
看上去是多么亲切啊,和sysfs文件系统初始化的代码还真是够相似的。首先,向系统注册文件系统类型dev_fs_type。其次,调用kern_mount_data(&dev_fs_type, options)来挂载文件系统,为devtmpfs创建的vfsmount对象也没有加入到vfsmount对象链表中,而是使用静态变量dev_mnt来指向devtmpfs的vfsmount对象。最后返回0。
在前面分析根文件系统挂载的时候,曾见到,同样是在kernel_init()函数中,调用了prepare_namespace()函数来执行挂载实际根文件系统,在这个函数中,我们看到,它调用了devtmpfs_mount("dev")函数来挂载devfs文件系统,而实际上大部分的前期准备工作,比如创建为devfs文件系统创建super_block对象、创建vfsmount对象及创建根目录项等这些工作则都是在devtmpfs_init()中完成的。
2、调用devices_init()函数来初始化devices子系统。
---------------------------------------------------------------------
drivers/base/core.c
int
__init devices_init(void)
{
devices_kset = kset_create_and_add("devices",
&device_uevent_ops, NULL);
if (!devices_kset)
return -ENOMEM;
dev_kobj =
kobject_create_and_add("dev", NULL);
if (!dev_kobj)
goto dev_kobj_err;
sysfs_dev_block_kobj =
kobject_create_and_add("block", dev_kobj);
if (!sysfs_dev_block_kobj)
goto block_kobj_err;
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"和"dev"这两个字符串也是眼熟的很啊。不正是/sys/目录中的两个子目录名嘛。在这里,我们再不能放过可以好好看看kset_create_and_add()和kobject_create_and_add()的机会了。不过,其实这里对kobject的用法算是比较怪的那种了吧,全都是只创建一个干巴巴的kobject对象,而没有被嵌入在一个内核对象中。和单独创建的某些list_head作为链表头类似,这里创建的也都是sysfs的“链表头”。他们被称为"simple" kobject,创建他们的唯一目的便是在sysfs文件系统中创建目录。
首先,看下kobject_create_and_add()的定义如下:
---------------------------------------------------------------------
lib/kobject.c
634
/**
635 * kobject_create_and_add - create a struct
kobject dynamically and register it with sysfs
636 *
637 * @name: the name for the kset
638 * @parent: the parent kobject of this
kobject, if any.
639 *
640 * This function creates a kobject structure
dynamically and
641 * registers it with sysfs. When you are finished with this
642 * structure, call kobject_put() and the
structure will be
643 * dynamically freed when it is no longer
being used.
644 *
645 * If the kobject was not able to be created,
NULL will be returned.
646 */
647
struct kobject *kobject_create_and_add(const char *name, struct kobject
*parent)
648
{
649 struct kobject *kobj;
650 int retval;
651
652 kobj = kobject_create();
653 if (!kobj)
654 return NULL;
655
656 retval = kobject_add(kobj, parent,
"%s", name);
657 if (retval) {
658 printk(KERN_WARNING "%s:
kobject_add error: %d\n",
659 __func__, retval);
660 kobject_put(kobj);
661 kobj = NULL;
662 }
663 return kobj;
664
}
665
EXPORT_SYMBOL_GPL(kobject_create_and_add);
---------------------------------------------------------------------
这个函数完成如下操作:
a.调用kobject_create()创建并初始化一个kobject对象。kobject_create()定义为:
---------------------------------------------------------------------
lib/kobject.c
606
static struct kobj_type dynamic_kobj_ktype = {
607 .release = dynamic_kobj_release,
608 .sysfs_ops = &kobj_sysfs_ops,
609
};
610
611
/**
612 * kobject_create - create a struct kobject
dynamically
613 *
614 * This function creates a kobject structure
dynamically and sets it
615 * up to be a "dynamic" kobject with
a default release function set up.
616 *
617 * If the kobject was not able to be created,
NULL will be returned.
618 * The kobject structure returned from here
must be cleaned up with
619 * a call to kobject_put() and not kfree(), as
kobject_init() has
620 * already been called on this structure.
621 */
622
struct kobject *kobject_create(void)
623
{
624 struct kobject *kobj;
625
626 kobj = kzalloc(sizeof(*kobj),
GFP_KERNEL);
627 if (!kobj)
628 return NULL;
629
630 kobject_init(kobj, &dynamic_kobj_ktype);
631 return kobj;
632
}
---------------------------------------------------------------------
kobject_create()函数首先为kobject对象分配内存,紧接着便是调用kobject_init(kobj, &dynamic_kobj_ktype)来初始化新创建的kobject。
---------------------------------------------------------------------
lib/kobject.c
145
static void kobject_init_internal(struct kobject *kobj)
146
{
147 if (!kobj)
148 return;
149 kref_init(&kobj->kref);
150 INIT_LIST_HEAD(&kobj->entry);
151 kobj->state_in_sysfs = 0;
152 kobj->state_add_uevent_sent = 0;
153 kobj->state_remove_uevent_sent = 0;
154 kobj->state_initialized = 1;
155
}
258
/**
259 * kobject_init - initialize a kobject
structure
260 * @kobj: pointer to the kobject to initialize
261 * @ktype: pointer to the ktype for this
kobject.
262 *
263 * This function will properly initialize a
kobject such that it can
264 * then be passed to the kobject_add() call.
265 *
266 * After this function is called, the kobject
MUST be cleaned up by
267 * a call to kobject_put(), not by a call to
kfree directly to ensure
268 * that all of the memory is cleaned up
properly.
269 */
270
void kobject_init(struct kobject *kobj, struct kobj_type *ktype)
271
{
272 char *err_str;
273
274 if (!kobj) {
275 err_str = "invalid kobject
pointer!";
276 goto error;
277 }
278 if (!ktype) {
279 err_str = "must have a ktype to be
initialized properly!\n";
280 goto error;
281 }
282 if (kobj->state_initialized) {
283 /* do not error out as sometimes we can
recover */
284 printk(KERN_ERR "kobject (%p):
tried to init an initialized "
285 "object, something is seriously
wrong.\n", kobj);
286 dump_stack();
287 }
288
289 kobject_init_internal(kobj);
290 kobj->ktype = ktype;
291 return;
292
293
error:
294 printk(KERN_ERR "kobject (%p):
%s\n", kobj, err_str);
295 dump_stack();
296
}
297
EXPORT_SYMBOL(kobject_init);
---------------------------------------------------------------------
一切真理都在代码之中,而代码又是那么的清晰,注释写的也好,没有什么必要废话了。可见,获得真理也不是那么的困难的。
b.调用kobject_add(kobj,
parent, "%s", name)将创建的kobject添加进kobject层次结构中。这个函数定义如下:
---------------------------------------------------------------------
lib/kobject.c
313
/**
314 * kobject_add - the main kobject add function
315 * @kobj: the kobject to add
316 * @parent: pointer to the parent of the
kobject.
317 * @fmt: format to name the kobject with.
318 *
319 * The kobject name is set and added to the
kobject hierarchy in this
320 * function.
321 *
322 * If @parent is set, then the parent of the
@kobj will be set to it.
323 * If @parent is NULL, then the parent of the
@kobj will be set to
324 * the kobject associted with the kset
assigned to this kobject. If
325 * no kset is assigned to the kobject, then
the kobject will be located
326 * in the root of the sysfs tree.
327 *
328 * If this function returns an error,
kobject_put() must be called
329 * to properly clean up the memory associated
with the object.
330 * Under no instance should the kobject that
is passed to this function
331 * be directly freed with a call to kfree(),
that can leak memory.
332 *
333 * Note, no "add" uevent will be
created with this call, the caller
334 * should set up all of the necessary sysfs
files for the object and
335 * then call kobject_uevent() with the
UEVENT_ADD parameter to ensure
336 * that userspace is properly notified of this
kobject's creation.
337 */
338
int kobject_add(struct kobject *kobj, struct kobject *parent,
339 const char *fmt, ...)
340
{
341 va_list args;
342 int retval;
343
344 if (!kobj)
345 return -EINVAL;
346
347 if (!kobj->state_initialized) {
348 printk(KERN_ERR "kobject '%s'
(%p): tried to add an "
349 "uninitialized object,
something is seriously wrong.\n",
350 kobject_name(kobj), kobj);
351 dump_stack();
352 return -EINVAL;
353 }
354 va_start(args, fmt);
355 retval = kobject_add_varg(kobj, parent,
fmt, args);
356 va_end(args);
357
358 return retval;
359
}
360
EXPORT_SYMBOL(kobject_add);
---------------------------------------------------------------------
kobject_add()函数首先检查kobject指针的是否为NULL,若是,则直接返回-EINVAL。然后调用kobject_add_varg(kobj, parent, fmt, args)来设置kobject的名字,并将其添加进sysfs层次结构中。
kobject_add_varg()函数定义为:
---------------------------------------------------------------------
lib/kobject.c
299
static int kobject_add_varg(struct kobject *kobj,
300 struct kobject *parent, const char
*fmt, va_list vargs)
301
{
302 int retval;
303
304 retval = kobject_set_name_vargs(kobj, fmt,
vargs);
305 if (retval) {
306 printk(KERN_ERR "kobject: can
not set name properly!\n");
307 return retval;
308 }
309 kobj->parent = parent;
310 return kobject_add_internal(kobj);
311
}
---------------------------------------------------------------------
这个函数首先调用kobject_set_name_vargs(kobj, fmt, vargs)来为kobject设置适当的名字。其次,设置kobj->parent指向传递进来的父kobject地址。最后调用kobject_add_internal(kobj)来向sysfs添加kobject。对于sys根目录下的目录,其parent为NULL。
来看kobject_add_internal()函数的定义:
---------------------------------------------------------------------
lib/kobject.c
158
static int kobject_add_internal(struct kobject *kobj)
159
{
160 int
error = 0;
161 struct kobject *parent;
162
163 if (!kobj)
164 return
-ENOENT;
165
166 if (!kobj->name || !kobj->name[0]) {
167 WARN(1, "kobject: (%p): attempted to be
registered with empty "
168 "name!\n", kobj);
169 return
-EINVAL;
170 }
171
172 parent = kobject_get(kobj->parent);
173
174 /* join kset if set, use it as parent if we
do not already have one */
175 if (kobj->kset) {
176 if (!parent)
177 parent =
kobject_get(&kobj->kset->kobj);
178 kobj_kset_join(kobj);
179 kobj->parent
= parent;
180 }
181
182 pr_debug("kobject: '%s' (%p): %s:
parent: '%s', set: '%s'\n",
183 kobject_name(kobj), kobj, __func__,
184 parent ? kobject_name(parent) :
"
185 kobj->kset
? kobject_name(&kobj->kset->kobj) : "
186
187 error = create_dir(kobj);
188 if (error) {
189 kobj_kset_leave(kobj);
190 kobject_put(parent);
191 kobj->parent = NULL;
192
193 /* be noisy on error issues */
194 if (error == -EEXIST)
195 printk(KERN_ERR "%s failed for
%s with "
196 "-EEXIST, don't try to
register things with "
197 "the same name in the
same directory.\n",
198 __func__,
kobject_name(kobj));
199 else
200 printk(KERN_ERR "%s failed for
%s (%d)\n",
201 __func__, kobject_name(kobj),
error);
202 dump_stack();
203 } else
204 kobj->state_in_sysfs = 1;
205
206 return error;
207
}
---------------------------------------------------------------------
这个函数,完成将kobject添加进sysfs系统的工作。在sysfs层次结构中创建目录的具体细节在后面的“在sysfs文件系统中创建目录”一文中会有更详细的说明。
其次,来看kset_create_and_add()函数,这个函数动态的创建一个kset结构并将其添加进sysfs中。其定义为:
---------------------------------------------------------------------
lib/kobject.c
820
/**
821 * kset_create_and_add - create a struct kset
dynamically and add it to sysfs
822 *
823 * @name: the name for the kset
824 * @uevent_ops: a struct kset_uevent_ops for
the kset
825 * @parent_kobj: the parent kobject of this
kset, if any.
826 *
827 * This function creates a kset structure
dynamically and registers
828 * it with sysfs. When you are finished with this structure,
call
829 * kset_unregister() and the structure will be
dynamically freed when
830 * it is no longer being used.
831 *
832 * If the kset was not able to be created,
NULL will be returned.
833 */
834
struct kset *kset_create_and_add(const char *name,
835
const struct kset_uevent_ops *uevent_ops,
836 struct
kobject *parent_kobj)
837
{
838 struct kset *kset;
839 int error;
840
841 kset = kset_create(name, uevent_ops,
parent_kobj);
842 if (!kset)
843 return NULL;
844 error = kset_register(kset);
845 if (error) {
846 kfree(kset);
847 return NULL;
848 }
849 return kset;
850
}
851
EXPORT_SYMBOL_GPL(kset_create_and_add);
---------------------------------------------------------------------
这个函数完成如下操作:
a.调用kset_create(name,
uevent_ops, parent_kobj)来动态地创建一个kset。kset_create()定义为:
---------------------------------------------------------------------
lib/kobject.c
771
static struct kobj_type kset_ktype = {
772 .sysfs_ops = &kobj_sysfs_ops,
773 .release = kset_release,
774
};
776
/**
777 * kset_create - create a struct kset
dynamically
778 *
779 * @name: the name for the kset
780 * @uevent_ops: a struct kset_uevent_ops for
the kset
781 * @parent_kobj: the parent kobject of this
kset, if any.
782 *
783 * This function creates a kset structure
dynamically. This
784 * structure can then be registered with the
system and show up in
785 * sysfs with a call to kset_register(). When you are finished with
786 * this structure, if kset_register() has been
called, call
787 * kset_unregister() and the structure will be
dynamically freed when
788 * it is no longer being used.
789 * If the kset was not able to be created,
NULL will be returned.
790 */
791
static struct kset *kset_create(const char *name,
792 const struct kset_uevent_ops *uevent_ops,
793 struct kobject
*parent_kobj)
794
{
795 struct kset *kset;
796 int retval;
797
798 kset = kzalloc(sizeof(*kset),
GFP_KERNEL);
799 if (!kset)
800 return NULL;
801 retval = kobject_set_name(&kset->kobj,
name);
802 if (retval) {
803 kfree(kset);
804 return NULL;
805 }
806 kset->uevent_ops = uevent_ops;
807 kset->kobj.parent = parent_kobj;
808
809 /*
810 * The kobject of this kset will have
a type of kset_ktype
811 * and belong to no kset itself. That way we can properly
812 * free it when it is finished being
used.
813 */
814 kset->kobj.ktype = &kset_ktype;
815 kset->kobj.kset = NULL;
816
817 return kset;
818
}
---------------------------------------------------------------------
这个函数执行如下操作:
(1).调用kzalloc(sizeof(*kset),
GFP_KERNEL)来为kset分配内存。
(2).调用kobject_set_name(&kset->kobj,
name)来为kset内嵌的kobject设置名字。kobject_set_name()定义为:
---------------------------------------------------------------------
lib/kobject.c
236
/**
237 * kobject_set_name - Set the name of a
kobject
238 * @kobj: struct kobject to set the name of
239 * @fmt: format string used to build the name
240 *
241 * This sets the name of the kobject. If you have already added the
242 * kobject to the system, you must call
kobject_rename() in order to
243 * change the name of the kobject.
244 */
245
int kobject_set_name(struct kobject *kobj, const char *fmt, ...)
246
{
247 va_list vargs;
248 int retval;
249
250 va_start(vargs, fmt);
251 retval = kobject_set_name_vargs(kobj,
fmt, vargs);
252 va_end(vargs);
253
254 return retval;
255
}
256
EXPORT_SYMBOL(kobject_set_name);
---------------------------------------------------------------------
(3).设置kset的kset->uevent_ops为传递进来的uevent_ops。
(4).设置kset的kset->kobj.ktype指向静态变量&kset_ktype,以使kset在引用计数变为0时能够得到系统正确的处理。
(5).设置kset->kobj.kset为NULL。
b.调用kset_register(kset)来初始化并向系统注册注册新创建的kset。这个函数定义为:
---------------------------------------------------------------------
lib/kobject.c
708
/**
709 * kset_register - initialize and add a kset.
710 * @k: kset.
711 */
712
int kset_register(struct kset *k)
713
{
714 int err;
715
716 if (!k)
717 return -EINVAL;
718
719 kset_init(k);
720 err = kobject_add_internal(&k->kobj);
721 if (err)
722 return err;
723 kobject_uevent(&k->kobj,
KOBJ_ADD);
724 return 0;
725
}
---------------------------------------------------------------------
这个函数执行的操作如下:
(1).调用kset_init(k)来初始化kset。而这个函数本质上是调用kobject_init_internal(&k->kobj)初始化kset内嵌的kobject,然后初始化kset的用于连接所属的kobject的list字段和用于保护kset的自旋锁list_lock字段。
(2).调用kobject_add_internal(&k->kobj)来将kset内嵌的kobject添加进系统。在sysfs层次结构中创建目录的具体细节在后面的“在sysfs文件系统中创建目录”一文中会有更详细的说明。
(3).
在向系统kobject核注册了kobject之后,则调用kobject_uvent(&k->kobj,
KOBJ_ADD),来向用户空间宣告kobject的建立,用户空间的守护进程会查找kobject的attributes。
总的来说,devices子系统建立过程主要创建并向系统注册了为devices子系统建立的kset,并由全局变量devices_kset指向这个kset,对应于sysfs文件系统根目录下的“devices”目录。为devices子系统创建了kobject,由静态变量dev_kobj指向这个kobject,对应于sysfs文件系统中的“dev”目录。为字符设备和块设备系统以dev_kobj为父kobject,创建两个kobject,分别由全局变量sysfs_dev_char_kobj和sysfs_dev_block_kobj指向这两个kobject。
3、调用buses_init()来初始化总线子系统。buses_init()定义如下:
---------------------------------------------------------------------
driver/base/bus.c
int
__init buses_init(void)
{
bus_kset =
kset_create_and_add("bus", &bus_uevent_ops, NULL);
if (!bus_kset)
return -ENOMEM;
return 0;
}
---------------------------------------------------------------------
这个函数只是为bus子系统在sysfs根目录下创建kset而已。由静态变量bus_kset指向这个kset。
4、调用classes_init()来创建类子系统。其定义为:
---------------------------------------------------------------------
driver/base/class.c
int
__init classes_init(void)
{
class_kset =
kset_create_and_add("class", NULL, NULL);
if (!class_kset)
return -ENOMEM;
return 0;
}
---------------------------------------------------------------------
创建sysfs层次体系的故事仍然在继续,这个函数也只是为class子系统在sysfs根目录下创建kset而已。由静态变量class_kset指向这个kset。
5、调用firmware_init()来创建firmware子系统。其定义为:
---------------------------------------------------------------------
driver/base/firmware.c
int
__init firmware_init(void)
{
firmware_kobj =
kobject_create_and_add("firmware", NULL);
if (!firmware_kobj)
return -ENOMEM;
return 0;
}
---------------------------------------------------------------------
为firmware子系统创建kobject,并有全局变量firmware_kobj指向这个kobject。
6、调用hypervisor_init()来初始化hypervisor子系统。其定义为:
---------------------------------------------------------------------
driver/base/hypervisor.c
int
__init hypervisor_init(void)
{
hypervisor_kobj =
kobject_create_and_add("hypervisor", NULL);
if (!hypervisor_kobj)
return -ENOMEM;
return 0;
}
---------------------------------------------------------------------
为hypervisor子系统创建kobject,并有全局变量hypervisor_kobj指向这个kobject。
看看driver_init()中的注释写的多有意思,下面的函数是core pieces,而上面的函数则都是core core pieces。
7、调用platform_bus_init()来初始化平台总线子系统。平台总线是一个虚拟总线,系统用它来做一些电源管理等工作。platform_bus_init()定义为:
---------------------------------------------------------------------
drivers/base/platform.c
1011
struct bus_type platform_bus_type = {
1012 .name = "platform",
1013 .dev_attrs = platform_dev_attrs,
1014 .match = platform_match,
1015 .uevent = platform_uevent,
1016 .pm = &platform_dev_pm_ops,
1017
};
1018
EXPORT_SYMBOL_GPL(platform_bus_type);
1019
1020
int __init platform_bus_init(void)
1021
{
1022 int error;
1023
1024 early_platform_cleanup();
1025
1026 error =
device_register(&platform_bus);
1027 if (error)
1028 return error;
1029 error = bus_register(&platform_bus_type);
1030 if (error)
1031
device_unregister(&platform_bus);
1032 return error;
1033
}
---------------------------------------------------------------------
这个函数,首先清理平台设备表,其次向系统注册平台总线设备,最后向系统注册平台总线类型。
8、调用system_bus_init()来建立系统总线子系统。其定义为:
---------------------------------------------------------------------
drivers/base/sys.c
501
int __init system_bus_init(void)
502
{
503 system_kset =
kset_create_and_add("system", NULL, &devices_kset->kobj);
504 if (!system_kset)
505 return -ENOMEM;
506 return 0;
507
}
---------------------------------------------------------------------
这个函数为系统总线子系统创建kset,并由静态变量system_kset指向这个kset。这个kset对应于sysfs文件系统根目录的“system”目录。
9、调用cpu_dev_init()来向系统注册CPU系统设备类。其定义为:
---------------------------------------------------------------------
drivers/base/cpu.c
250
int __init cpu_dev_init(void)
251
{
252 int err;
253
254 err =
sysdev_class_register(&cpu_sysdev_class);
255
#if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT)
256 if (!err)
257 err = sched_create_sysfs_power_savings_entries(&cpu_sysdev_class);
258
#endif
259
260 return err;
261
}
---------------------------------------------------------------------
10、调用memory_dev_init()来初始化sysfs对存储器设备的支持。其定义为:
---------------------------------------------------------------------
drivers/base/memory.c
535
/*
536 * Initialize the sysfs support for memory
devices...
537 */
538
int __init memory_dev_init(void)
539
{
540 unsigned int i;
541 int ret;
542 int err;
543
544 memory_sysdev_class.kset.uevent_ops =
&memory_uevent_ops;
545 ret =
sysdev_class_register(&memory_sysdev_class);
546 if (ret)
547 goto out;
548
549 /*
550 * Create entries for memory sections
that were found
551 * during boot and have been
initialized
552 */
553 for (i = 0; i < NR_MEM_SECTIONS;
i++) {
554 if (!present_section_nr(i))
555 continue;
556 err = add_memory_block(0,
__nr_to_section(i), MEM_ONLINE,
557 BOOT);
558 if (!ret)
559 ret = err;
560 }
561
562 err = memory_probe_init();
563 if (!ret)
564 ret = err;
565 err = memory_fail_init();
566 if (!ret)
567 ret = err;
568 err = block_size_init();
569 if (!ret)
570 ret = err;
571
out:
572 if (ret)
573 printk(KERN_ERR "%s() failed:
%d\n", __func__, ret);
574 return ret;
575
}
---------------------------------------------------------------------
OK,到此为止Driver Model初始化结束。
我们的目标应该说基本达到,我们了解到kobject在sysfs文件系统中对应一个目录,而属性则对应一个文件,我们看到了sysfs文件系统中比较顶层的一些目录的创建过程。Sysfs的目录在添加进系统的时候有sysfs文件系统中的特定代码创建。接下来我们会仔仔细细的看一下目录的创建过程。
没有弄明白的:许许多多用于在sysfs文件系统中创建文件的接口的原理。还有总线、设备、平台设备等等这些与底层硬件关系密切的子系统。要等回头开发驱动时候,有需要再来仔细审视这些东西了。