c语言中的面向对象(1)----kobject 和 container_of

最近看驱动开发,看linux的device model,有一些感触。暂记于下。

我之前一直把OO(object oriented)这个概念和特定的语言联系在一起。比如,认为c++,java,python等是面向对象的语言,C语言就不是。这种想法不太对,而且有时很危险,至少,这样的想法会限制你解决问题的思路。

OO和语言应该分开来看。OO是一种解决问题的概念,是对问题的一种抽象;而编程语言,是解决问题的工具。

以下线简单谈谈kobject和container_of.

从oo的观点来看,kobject就是一个super class, 配合container_of这个宏,实现了运行时的动态绑定特性。

在kernel中,几乎所有的device,都会有一个kobject域,比如cdev

struct cdev {
    struct kobject kobj;
    struct module *owner;
    struct file_operations *ops;
    struct list_head list;
    dev_t dev;
    unsigned int count;
};

这个kobject是用来提供一些基础服务的,如reference counting, data structure glue, hotplug handing等。我们可以把这些structure都看成是kobject的派生类。那么问题就来了,这些派生类会有很多种,而他们的好多操作,从含义上来讲,是一样的,比如create,比如remove等。我们自然可以为每一个类定义它对应的操作,这对实现没有问题。但是,上层调用这些类的时候,面对每一个含义相似的操作却有不同的参数类型,会是何等蛋疼的一件事情!!!

在c++中,我们是通过传递基类指针或者引用的方式,通过动态绑定来解决这个问题的。

但是,c语言没有内建这种面向对象的机制。它是如何来解决这个问题的呢?

今天,简单只谈一点:container_of

 

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

这个宏的作用是,通过结构的一个域,来取得该结构的指针。

比如有某个kobject* pk指向某个kobject。而此kobject是cdev中一员。可以用以下语句,取得该cdev结构的指针

container_of(pk, cdev, kobj);

因为所有device structure都包含kobject域,所以,我们可以给一些语义想通的操作,传递kobject指针,而在函数内部,利用container_of来取得实际的对象的指针,从而进行相应操作。

以下,简单解析下container_of宏。

其结构是({A;B;})。主要原理是通过指针操作(加减一定的数值)以及强制类型转换,来返回指向某个内存的一个特定类型的指针。原理比较简单,有两点可能会有些疑惑,如下。

1.({A;B;})的含义。 对c和c++熟悉的人应该知道,它返回的值是B表达式的值。怀疑的可以试一下printf("%d", ({1;2;3;});

2.typeof的含义。typeof是c新引进的关键词。参考如下连接。typeof的实现方法想来比较简单,就是在稍微改下编译器的实现就ok了。在编译器关键词中天剑typeof,然后进行语法处理的时候对typeof的表达式进行分析求值。

http://gcc.gnu.org/onlinedocs/gcc/Typeof.html

转载于:https://my.oschina.net/u/158589/blog/36054

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值