1. 就目前的linux内核代码中,驱动程序 这块可以说是用C语言进行面向对象编程的一个很好的例子,另外还有一个例子是文件系统部分 。
驱动这块的布局是:
struct usb_interface 包含一个struct device,而struct device包含一个struct kobject结构,struct kobject又包含struct kref。
需要说明的是:(1)kobject 结构体是用来统一的显示不同的设备 ,以及和这些设备相联系的虚拟文件系统 ,这个结构仅具有非常基础的功能,包括引用计数,被插入到对象层次结构中。
(2)kref是一个只有一个成员: atomic_t refcount; 的结构。 他主要是考虑到:多线程程序设计中,每个开发者为了管理内存,都需要在结构中加入引用计数,因此,就单独抽出来。
所以这里用到的从基类到子类的顺序为:
struct kref -> struct kobject -> struct device -> struct usb_interface
这个例子就是c中的继承,它利用了结构体之间的组合关系。
2. 用C实现面向对象,子类中包含有基类,因此知道了子类很容易就可以获得基类的信息;但是,如果已知子类中的基类,能不能反查找不它所在的基类的信息呢? 答案是可以,在linux内核中,是使用一个宏来做这个事情的:
#define container_of ( ptr , type, member) ( { /
const typeof ( ( (type *) 0 ) -> member ) * _mptr = (ptr); /
(type * ) ( (char *) _mptr - offsetof (type, member) ) ; /
})
这里: (1) 显然offsetof这个编译器宏仍然可以用 (type*)0->member这样的方法取代,或者说是实现
(2) 要看清楚,最后那里是 相减 获得该子类结构的起始地址!
该宏的一个调用例子为:
int probe (struct device* d )
{
struct usb_interface *intf;
intf = container_of ( d, struct usb_interface , dev);
//解析一下上面那个宏,就是:
const struct device* _mptr = d;
intf = (struct usb_interface*)( (char*)_mptr - offset(type,member) );
#define offset(type,member) (size_t)&(((type*)0)->member)
// dev 是 struct usb_interface中的一个成员名称,该成员的类型是strcut device;
...
}
}
(附: tree这个命令是以树的形式显示,文件夹下的所有文件,包括子目录的方式~
非常的实用!)