设备管理已经成为现代统项重要任务,Linux每次内核新版本的发布,会伴随着一批设备驱动进入内核。Linux驱动程序的代码量占有了相当大的比重。图是我在网络上搜索到的一幅内核代码量的统计图,2.6.29。们可以很明Linux驱动程序的比例已
内核最初应付个设备模型设备。在物理上,外间是有一关系的,比如把一U笔记本上,这个盘是接在一USB Hub上,USB 2.0 Host Controller (EHCI)上,最EHCI又是一PCI Bus上的这里的一关系是:统要状态,首先要逐设进入休眠模式,然后整统才可以休眠。因此,需要有一结构可以把所有的外来。Linux
Linux给我远不止如此。经建立了一设备和树状结构,用过这棵树去遍设备,建立驱动程序之联系,根据对设备进行这样就可以更“看这颗枝繁叶茂的大Linux设备共有的一些操作抽象出减少了重轮子的可能。同Linux辅助的机制,比如引用让开发者可以安全高效的达成了以上处之后,我个非常方便的副这就是个虚拟的文件系sysfs户提供了一户空访问内核它在径是这个目储在硬真实的文件系统启动之后才来。这个命令可以用sysfs的大致
这个命令的信息量非常大,我就不来了,如果有话可以看看动手 我层目
这里有个子目录,并不是说这个目录代表了种完全不同的设备类型,其那看看目对,devices录,的所有这里是一个大杂烩,这里还是以盘为例,U在目U真得很难办到。这个盘在系统里的设备文件名(sdb),从目
透block目们很容易就可以找到U号链接devices目 到们总结一下录下各录的作用。录是来组织设备;录是统总线这个角度这里的实际意总线比如总线,也可以是完全总线比如总线;录把看视角提高到了PCIUSBdev目视角是devices目这里是所有营;录包含了一些比阶的子系ACPI、fs目统支持的所有文件系kernel目内核的配置modules目内核模内核模设备之对应关系的,通录顺藤摸瓜找到过来都是可以做到的;录存放的是系数据,用过它来查询目前的状态,甚至可以直接”系电模式。sysfs正是用内核间的一座过这个桥梁我从内核中内核里 在图形化的工具GNOME下基于Device Manager:KDE下基于KInfoCenter:这些观的方式它们的提供的信息够全面,而且内核 如果具体到某一设备,还有一些PCIpciutils,面向设备的SCSIlsscsi等。Linux来说,有这些 另外,我写程序sysfs,可以使用来实现。访问设备,一般很少libsysfs层的况下可以使用比阶的libudev。总结一下,本文主要绍了设备模型的基本虚拟文件系sysfs。接下将和大家讨设备模型在间的一些 上一篇文章《设备模型》绍了设备模型在用户空间的接口用本文Linux 在内核里,组成设备模型的基个对应个目从面向来说,设备对象的基为语言对象的kobject结构体里这里的其他kobject的派生KobjectLinux计数,接口抽象,父子计数本krefkref的参考我之前的文章《内核里的针 另外,设备模型个重要的结构Kset本身也是一kobject,所以sysfs里同现为一录,但kobject的不同之kset可以看作是一你把为类如Kset之所以能作来使用,其内嵌了一链表struct list_head。这幅来表示kset在关系。来的篇幅里我这个关系内核里是如何建立的。本文的示例代从这里下两个实作都在码里。KobjectKobject在内核里的定
Linux们介内核里的间是以组织的,在构里比层的层节点的父sysfs里就是上录和下录之关系,在kobject们实现这种父子kobject的定name表示的是sysfs中的名字;指parent用kobject的父Kref大家较熟悉了,过它来实现引用Kset指来指向kobject所kset,下文详细描述对于义的应该是用kobject的Ktype的定
函release给使用的,0sysfs_opsattribute么用的呢?一kobjectsysfs个目录,录下的文件就是由和来实现的,attribute义了的在里sysfs_ops来定义读写这个文件的方法。里的是默另外也可以使用更加本文的重点default attribute。个实作。在们定个内嵌结构。struct my_kobj { int val; struct kobject kobj; }; |
最们的目的是在构建构。对应录关系是:mykobj1/ |-- mykobj2 | |-- name | `-- val |-- name `-- val |
module_init代
obj1 = kzalloc(sizeof(struct my_kobj), GFP_KERNEL); if (!obj1) { return -ENOMEM; } obj1->val = 1; my_type.release = obj_release; my_type.default_attrs = my_attrs; my_type.sysfs_ops = &my_sysfsops; return 0; } |
第一部分是分配和并赋值;kobj_typemy_type;调用函kobject也就是上文中提到的中。是这个函数也可以分两步完成:和
void kobject_init(struct kobject *kobj, struct kobj_type *ktype); int kobject_add(struct kobject *kobj, struct kobject *parent, const char *fmt, ...); |
来初始化结构,来把设备模型之中。在们先obj1动作,参数里,赋为obj1对象,反映到my_kobj1的目现在obj2的父设定obj1,那my_kobj2的目现在 前面提到,计数的功能,质上是利用户使用。struct kobject *kobject_get(struct kobject *kobj); kobject_init_and_add和这两个函调用后,计数会初始化1,所以在时要kobject_put计数。们再回到ktype。代my_attrs是义的:struct attribute name_attr = { .name = "name", .mode = 0444, }; .name" 0666="" style="TEXT-ALIGN: left; LINE-HEIGHT: 21.6pt; MARGIN: 7.5pt 0cm; TEXT-AUTOSPACE: ideograph-numeric; WORD-BREAK: keep-all; mso-pagination: widow-orphan" class="MsoNormal" align="left" color="#333333" face="">struct attribute *my_attrs[] = { &name_attr, &val_attr, NULL, }; |
struct attribute里的变量用mode来指定文件的这里需要着重指出的是,my_attrs的最后一赋为则会造成oops。sysfs_ops的代
" style="TEXT-ALIGN: left; LINE-HEIGHT: 21.6pt; MARGIN: 7.5pt 0cm; TEXT-AUTOSPACE: ideograph-numeric; WORD-BREAK: keep-all; mso-pagination: widow-orphan" class="MsoNormal" align="left" color="#333333" face=""> if (strcmp(attr->name, "name") == 0) { count = sprintf(buffer, "%s/n", kobject_name(kobj)); } else if (strcmp(attr->name, "val") == 0) { count = sprintf(buffer, "%d/n", obj->val); }ssize_t my_store(struct kobject *kobj, struct attribute *attr, const char *buffer, size_t size) { struct my_kobj *obj = container_of(kobj, struct my_kobj, kobj); return size; } .show" my_show="" my_store="" style="TEXT-ALIGN: left; LINE-HEIGHT: 21.6pt; MARGIN: 7.5pt 0cm; TEXT-AUTOSPACE: ideograph-numeric; WORD-BREAK: keep-all; mso-pagination: widow-orphan" class="MsoNormal" align="left" color="#333333" face="">读文件会调用写文件会调用 最后是
kobject_del(&obj2->kobj); kobject_put(&obj2->kobj); kobject_del(&obj1->kobj); kobject_put(&obj1->kobj); kobject_del的作用是把从设备模型的那时应的目会删除。释放的应该是先子对象。因kobject_init_and_add和这两个函kobject_get对象的引用kobject_del需要kobject_put对象的引用过来释放kobject_del(&obj2->kobj)就现内存 在们建立了obj1和obj1是对象,如果推广obj1可以有更多的子Linux这种架实并无值。设备模型最初的目的是电源管理,从上到下的遍这种架过并无法对象。义只在于可以们比kobject如何使用。通常情kobject只需要在叶层的kset。KsetKset的定
Ksetkobj表明个list来组织它所有的子 我个实作。在们将构建如下的架
sysfs里的目
这个实作和前一个差别很小,简略的引用一些代码。static int __init mykset_init(void) { printk(KERN_INFO "mykset_init/n"); // Allocate obj1 and obj2 // ... // Init my_type // ... return 0; } // Release obj1 and obj2 // ... return; } |
在们首先kset_create_and_addmy_kset,接下my_ksetobj1和调用来添加obj2。kobject_init_and_addparent都是这种情obj1和对象由结构里的针决定,在my_kset。在们还需要调用来释放之前my_kset。过读者Linux Device Model一章中的还有印象,我在从开始内核就抛弃了subsystem其kset的一它对设备模型么影 |
|
|
|