一步一步粗谈linux文件系统(九)---- device_register

总结:挂载文件到device下(具体目录可能各有不同),如果是class,则有几个相互的链接。sysfsramfs不同的是,sysfs具体操作,文件建立,生成链接,都用struct kobject,而不是直接的应用dentry。最最简单的理解,就是把一个kobject挂到devices_subsys的kset上。

 

/**

 *        device_register- register a device with the system.

 *        @dev:        pointerto the device structure

 *

 *        Thishappens in two clean steps -initialize the device

 *        andadd it to the system. The two steps can be called

 *        separately,but this is the easiest and most common.

 *        I.e.you should only call the two helpers separately if

 *        havea clearly defined need to use and refcount the device

 *        beforeit is added to the hierarchy.

 */

 

intdevice_register(struct device *dev)

{

device_initialize(dev);        //初始化设备

//dev.kobj.kset=device_sbusys.kset

returndevice_add(dev);

}

按照注释里说明的那样,分两步,一是初始化,二是添加

 

第一部分:

/**

 *        device_initialize- init device structure.

 *        @dev:        device.

 *

 *        Thisprepares the device for use by other layers,

 *        includingadding it to the device hierarchy.

 *        Itis the first half of device_register(), if called by

 *        that,though it can also be called separately, so one

 *        mayuse @dev's fields (e.g. the refcount).

 */

 

voiddevice_initialize(struct device *dev)

这个函数里有一行代码kobj_set_kset_s(dev, devices_subsys);它的作用就是dev.kobj.kset=device_sbusys.kset //对象的kset指向devices_subsyskset

klist_init(&dev->klist_children,klist_children_get,

  klist_children_put);maybe也可以适当关注一下

 

第二部分:

/**

 *        device_add- add device to device hierarchy.

 *        @dev:        device.

 *

 *        Thisis part 2 of device_register(), though may be called

 *        separately_iff_ device_initialize() has been called separately.

 *

 *        This adds it to the kobject hierarchy via kobject_add(), addsit

 *        tothe global and sibling lists for the device,

 *    then adds it to the other relevant subsystems of the driver model.

 */

intdevice_add(struct device *dev)

 

这个函数很长很核心,且慢慢分析:

1

parent =get_device(dev->parent);

error =setup_parent(dev,parent);        //如果class存在且parent为NULL,则获取为class的virtual,

//是在/sys/device/virtual

//设置的是dev->kobj.parent,而非parent

//如果parent存在,则为parent。

这两行企图去获得parent,然后dev->kobj.parent指向这个父节点。这个在后面add,也就是挂载的时候很需要,

如果是NULL,也没关系,慢慢来

2

/* first, registerwith generic layer. */

kobject_set_name(&dev->kobj,"%s",dev->bus_id);        //名字

error =kobject_add(&dev->kobj);        //先dentry\inode\sd,一个都不少,然后父节点呢,是device

//dev->kobj->dentry=dentry

//然后父节点有张表,来存放新添加的obj

//这里其实已经挂载上去了。比如platform已经在device下面了

//dev->kobj->kset=device,you know?

这两行代码就是挂载,kobject_addsubsystem_register中已经有所分析。

最重要的是:

if (kobj->kset) {	//前提是kset要存在,如果是device,fs的subsystem 这项应该不存在
	spin_lock(&kobj->kset->list_lock);

	if (!parent)
		parent = kobject_get(&kobj->kset->kobj);	//如果父节点不存在,kset的对象就是父节点
							//如platform_type_bus的kobj->kset->kobj  就是device_subsys->kset->kobj
							//其实可以这么理解,如果父节点也没,kset也没,就直接挂在sys下
							//如果有父节点就挂在父节点下,如果有kset就挂在kset下

	list_add_tail(&kobj->entry,&kobj->kset->list);	//将kobj->entry加到kset的节点,需要信息是不是遍历这张表
	spin_unlock(&kobj->kset->list_lock);
}(kobject_shadow_add节选)

即使没有父节点,也会进入这里,进入这里意味着什么呢?结合初始化时候:dev.kobj.kset=device_sbusys.kset

也就是说即使没有父节点,那么父节点就是device_sbusys.kset,也就是说,如果初始父节点是NULL的话,那么就挂在device下,也就是sys/device这个目录下。

接下来跟前面subsystem中的kobject_add没什么差异了

3

dev->uevent_attr.attr.name= "uevent";

dev->uevent_attr.attr.mode= S_IWUSR;

if(dev->driver)

dev->uevent_attr.attr.owner= dev->driver->owner;

dev->uevent_attr.store= store_uevent;

error= device_create_file(dev,&dev->uevent_attr);        //生成文件挂载在设备目录上面

if(error)

gotoattrError;

这几行代码很容易理解,设置一个属性名问uevent的,然后将它挂载到上面挂载上的文件上去。

 

接下来有类似的代码,比如说如果是设备文件,就设置dev属性。

4 

	if (dev->class) {
		sysfs_create_link(&dev->kobj, &dev->class->subsys.kset.kobj,
				  "subsystem");	//将/sys/class/xxx挂至当前对象下
				//如/sys/class/tty挂至/sys/device/virtual/tty/ttyS0/subsystem
		/* If this is not a "fake" compatible device, then create the
		 * symlink from the class to the device. */
		if (dev->kobj.parent != &dev->class->subsys.kset.kobj)
			sysfs_create_link(&dev->class->subsys.kset.kobj,
					  &dev->kobj, dev->bus_id);	//将当前对象挂载到class下
					  		///sys/device/virtual/tty/ttyS0挂到/sys/class/tty
		if (parent) {
			sysfs_create_link(&dev->kobj, &dev->parent->kobj,
							"device");	//将父对象挂载到当前对象的device下
#ifdef CONFIG_SYSFS_DEPRECATED
			class_name = make_class_name(dev->class->name,
							&dev->kobj);
			if (class_name)
				sysfs_create_link(&dev->parent->kobj,
						  &dev->kobj, class_name);
#endif
		}

这段代码很有趣,如果设备有class,那么还要创建一个链接。上面的代码1里已经说了,如果有classparentNULL的话,那么dev->kobj是挂载device/virtual下的。

下面的图片很直观,创建是device/virtual/tty/ttyS0中的subsystem指向了class/tty


然后创建class/tty/ttyS0指向device/virtual/tty/ttyS0



5

后面的代码更像是在善后,前面大的基础已经打好了,后面的一些私有属性,该添加的添加。

if (parent)
		klist_add_tail(&dev->knode_parent, &parent->klist_children);

	if (dev->class) {
		down(&dev->class->sem);
		/* tie the class to the device */
		list_add_tail(&dev->node, &dev->class->devices);	//将当前节点添加至class设备链表中、
									//如ttys0添加到tty_class

		/* notify any interfaces that the device is here */
		list_for_each_entry(class_intf, &dev->class->interfaces, node)
			if (class_intf->add_dev)
				class_intf->add_dev(dev, class_intf);
		up(&dev->class->sem);
	}

dev->knode_parent添加到parent->klist_children的链表中。

 

这样方便管理查找


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值