全部博文(175)
分类: LINUX
2011-12-15 14:32:09
make -C /home/zxl/soft/kernel/linux-2.6.22 M=`pwd` clean
Sysfs文件系统与Linux设备模型
sysfs把连接在系统上的设备和总线组织成为一个分级的目录及文件,它们可以由用户空间存取,向用户空间导出内核数据结构以及它们的属性,这其中就包括设备的主次设备号。新的设备文件系统udev的工作过程就依赖于sysfs文件系统的这些功能特点。udev文件系统在用户空间工作,它可以根据sysfs文件系统导出的信息(设备号等),动态建立和删除设备文件,而不再需要使用mknod来手动建立设备文件,也不必为查找设备号(尤其是驱动中动态申请产生的设备号)而头疼。
kobject内核对象提供了基本的对象管理能力,是linux 2.6设备模型的核心结构,每个在内核中注册的kobject对象都对应于sysfs文件系统的一个目录,这可以通过以下函数调用体现:
kobject_add()-> kobject_add_varg()->kobject_add_internal()->create_dir()->sysfs_create_dir()
(好像已经不存在kobject_register函数了)
sysfs文件系统下的所有目录,其最终的建立过程都是通过注册添加kobject到linux设备层次来实现的,举两个例子:
1、class
class_register-> __class_register-> kset_register-> kobject_add_internal
2、device
device_register-> device_add-> kobject_add
因此,对应于一个设备,在sysfs文件系统下不是一个文件,而是一个目录,目录名字的来源是kobject对象的name域。目录中会有两个文件和若干目录,这两个文件是设备的属性文件。我们可以看看device_add函数的实现,其中有:
912 error = device_create_file(dev, &uevent_attr);
913 if (error)
914 goto attrError;
915
916 if (MAJOR(dev->devt)) {
917 error = device_create_file(dev, &devt_attr);
918 if (error)
919 goto ueventattrError;
其中会在sysfs文件系统对应设备目录下创建两个属性文件(可以看看device_create_file函数的实现,是调用sysfs_create_file),其中有两个参数是两个结构体指针,两个结构体的定义如下:
311 static struct device_attribute uevent_attr =
312 __ATTR(uevent, S_IRUGO | S_IWUSR, show_uevent, store_uevent);
428 static struct device_attribute devt_attr =
429 __ATTR(dev, S_IRUGO, show_dev, NULL);
再看看_ATTR:
48 #define __ATTR(_name,_mode,_show,_store) { \
49 .attr = {.name = __stringify(_name), .mode = _mode }, \
50 .show = _show, \
51 .store = _store, \
52 }
再看看__stringify:
19 #define __stringify_1(x) #x
20 #define __stringify(x) __stringify_1(x)
(真是无底洞呀,到这为止吧!)这两个宏看起来很怪异,有人说这个定义很奇妙,具体奇妙在哪目前我还没体会到,等有机会再补充(留个脚印吧)。简单来说,它们的功能就是x转化为字符串,所以uevent和dev就转化为“uevent”和”dev“了,把它们赋给name,这就是sysfs具体设备目录下的两个文件uevent和dev名字的来源了!
这两个属性文件的内容是怎么等到的呢?sysfs是虚拟文件系统,大家应该知道proc文件系统吧,类似地它们都是在内存中,内容都是动态生成的而不是存储在非易失存储器中。大家应该注意到属性结构体中有两个函数指针show和store,在这里被赋值了
422 static ssize_t show_dev(struct device *dev, struct device_attribute *attr,
423 char *buf)
424 {
425 return print_dev_t(buf, dev->devt);
426 }