发新话题
打印

挑战,一起分析Linux2.6设备驱动模型

挑战,一起分析Linux2.6设备驱动模型

   最近,西邮Linux兴趣小组的同学在学习Linux驱动程序的过程中,感到2.6内核的设备驱动模型错综复杂。而实际上,我查阅了相关的资料,包括《Understanding The Linux Kernel》  和《Linux Kernel development 》
两本书上的讲述,当时翻译这部分的时候,就觉得作者也没有完全说清楚,再在网上查阅相关资料,大都讲的都似是而非。面对这样有­挑战性的问题,是绕过去,仅仅模仿着驱动程序的框架,还是,深入进去,追究个所以然?
   目前,既然大家都卡在这个问题上,那么,我们干脆像庖丁一样,深入内部,理清十几个对象之间复杂的关系。如果,能把这种基础性的框架搞清楚,就像我们打扎实高楼­的地基,不仅让大家以后再阅读其他源代码会有除却巫山的感觉,还会为国内的驱动程序开发者提供最基础的中文参考资料。   99年,我和我学生们,从对内核的一无所知开始分析,阅读了大量的源代码,写出了国内第一本《Linux操作系统源代码分析》一书,那本书曾被指定为中科院考博­参考书。Everiything is possible!
设备驱动模型涉及的相关对象:
file结构体
inode结构体
devfs设备文件系统
udev设备文件系统
sysfs文件系统
kobject内核对象
kobj_type结构体
kset结构体
sybsystem结构体
device结构体
device_driver结构体
class结构体
class_device结构体
class_interface结构体

面对如此众多的结构体,从何入手,怎样进去?在此建议,还是从kobject这个核心结构体着手,从读kobject.h源代码走入




[ 本帖最后由 陈莉君 于 2008-7-20 16:25 编辑 ]
透析真谛,似拨云穿雾;共享智慧,如春风沐浴
http://www.kerneltravel.net

释义内核中灵活的宏

在kobject.h中有这样的宏定义:

185  #define decl_subsys(_name,_type,_uevent_ops) \
186  struct kset _name##_subsys = { \
187        .kobj = { .name = __stringify(_name) }, \
188        .ktype = _type, \
189        .uevent_ops =_uevent_ops, \
190}



其中 “_name##_subsys ”是什么含义? 实际上,"_name“是参数,"##"是字符串连接符,因此,上面就是申明了一个类型为 Struct kset,并以_subsys结尾的任意实例,例如:

struct kset  decive##_subsys ={...

}
透析真谛,似拨云穿雾;共享智慧,如春风沐浴
http://www.kerneltravel.net
在驱动程序开发中,经常遇到container_of()宏:

/**
312 * container_of - cast a member of a structure out to the containing structure
313 * @ptr:        the pointer to the member.
314 * @type:       the type of the container struct this is embedded in.
315 * @member:     the name of the member within the struct.
316 *
317 */



#define container_of(ptr, type, member) ({                    \        
        const typeof( ((type *)0)->member ) *__mptr = (ptr); -
\
        (type *)( (char *)__mptr - offsetof(type,member) );})

container_of()宏的功能是什么?


指针ptr指向结构体type中的成员member;通过指针ptr,返回结构体type的起始地址。
          type
      |----------|
      |          |
      |          |
      |----------|
ptr-->| member --|
      |----------|
      |          |
      |          |
      |----------|


其中offsetof宏定义在[include/linux/stddef.h]中定义为:
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

这里,要说明的是,((size_t) &((TYPE *)0)->MEMBER)把0地址转化为TYPE结构的指针,然后获取该结构中MEMBER成员的指针,并将其强制转换为size_t类型。于是,由于结构从0地址开始定义,因此,这样求出的MEMBER成员地址,实际上就是它在结构中的偏移量。这也显示出了C语言中指针的强大。因为,在某个体系结构下实现的libc,结构中各个成员的偏移总是可以预见的。

基于以上分析,大家分析container_of()为什么实现了那样的功能。

分析可知__mptr指向的是一个type结构里typeof(((type *)0)->member)类型member成员的指针,offsetof(type,member)是这个成员在结构中的偏移,单位是字节,所以为了计算type结构的起始地址,__mptr减去它自己的偏移。





[ 本帖最后由 陈莉君 于 2008-7-20 17:12 编辑 ]
透析真谛,似拨云穿雾;共享智慧,如春风沐浴
http://www.kerneltravel.net
刚才看到您说是取得member成员的地址,我还以为是我没看清,又看了一下http://blog.csdn.net/hotsolaris/archive/2007/10/14/1823808.aspx
肯定了是取得type的指针,就象您解释的那样。
羡慕西邮的同学们,有陈老师带队,幸福啊!
这些天我们基本把这些结构分析了一下,每个人都将分析写在博客中了,有兴趣的可以到我们的博客圈看看:
http://blog.chinaunix.net/group/group_1488.html
发新话题