最近看驅動開發,看linux的device model,有一些感觸。暫記於下。html
我以前一直把OO(object oriented)這個概念和特定的語言聯繫在一塊兒。好比,認爲c++,java,python等是面向對象的語言,C語言就不是。這種想法不太對,並且有時很危險,至少,這樣的想法會限制你解決問題的思路。java
OO和語言應該分開來看。OO是一種解決問題的概念,是對問題的一種抽象;而編程語言,是解決問題的工具。python
如下線簡單談談kobject和container_of.linux
從oo的觀點來看,kobject就是一個super class, 配合container_of這個宏,實現了運行時的動態綁定特性。c++
在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的表達式進行分析求值。