Chinaunix首页 | 论坛 | 博客
  • 博客访问: 819736
  • 博文数量: 117
  • 博客积分: 2583
  • 博客等级: 少校
  • 技术积分: 1953
  • 用 户 组: 普通用户
  • 注册时间: 2008-12-06 22:58
个人简介

Coder

文章分类
文章存档

2013年(1)

2012年(10)

2011年(12)

2010年(77)

2009年(13)

2008年(4)

分类: 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来指向devtmpfsvfsmount对象。最后返回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根目录下的目录,其parentNULL

 

来看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)来动态地创建一个ksetkset_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).设置ksetkset->uevent_ops为传递进来的uevent_ops

(4).设置ksetkset->kobj.ktype指向静态变量&kset_ktype,以使kset在引用计数变为0时能够得到系统正确的处理。

(5).设置kset->kobj.ksetNULL

 

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的用于连接所属的kobjectlist字段和用于保护kset的自旋锁list_lock字段。

 

(2).调用kobject_add_internal(&k->kobj)来将kset内嵌的kobject添加进系统。在sysfs层次结构中创建目录的具体细节在后面的“在sysfs文件系统中创建目录”一文中会有更详细的说明。

 

(3). 在向系统kobject核注册了kobject之后,则调用kobject_uvent(&k->kobj, KOBJ_ADD),来向用户空间宣告kobject的建立,用户空间的守护进程会查找kobjectattributes

 

总的来说,devices子系统建立过程主要创建并向系统注册了为devices子系统建立的kset,并由全局变量devices_kset指向这个kset,对应于sysfs文件系统根目录下的“devices”目录。为devices子系统创建了kobject,由静态变量dev_kobj指向这个kobject,对应于sysfs文件系统中的“dev”目录。为字符设备和块设备系统以dev_kobj为父kobject,创建两个kobject,分别由全局变量sysfs_dev_char_kobjsysfs_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初始化结束。

 

我们的目标应该说基本达到,我们了解到kobjectsysfs文件系统中对应一个目录,而属性则对应一个文件,我们看到了sysfs文件系统中比较顶层的一些目录的创建过程。Sysfs的目录在添加进系统的时候有sysfs文件系统中的特定代码创建。接下来我们会仔仔细细的看一下目录的创建过程。

 

没有弄明白的:许许多多用于在sysfs文件系统中创建文件的接口的原理。还有总线、设备、平台设备等等这些与底层硬件关系密切的子系统。要等回头开发驱动时候,有需要再来仔细审视这些东西了。

阅读(1606) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~