linux設備驅動程序學習筆記——container_of宏

   在open函數中,int (*open) (struct inode *inode,strcut file *flip); inode->i_cdev結構包含了我們在註冊時配置的cdev結構,但是我們實際真正需要的是包含cdev結構的scull結構,在open中,我們應當獲得這個scull結構的指針,方便以後的操作。如何獲得,要利用到container_of宏。

該宏定義在<linux/kernel.h>中

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

typeof 用於確定某個變量的實際類型,offsetof宏用於確定某個成員在結構體中的偏移值。

第一句話,僅僅是用來定義一個跟member同類型的指針,這裏可理解爲臨時變量。我們在定義一個宏時,如果也需要和參數相同的臨時變量,就可以採用這種方法。這裏的(type*)0,假定有一個在0地址的type類型指針,因爲這不牽涉到讀寫,所以安全上沒有問題。這裏的0可以爲任意都可以,在這裏僅僅是獲得變量類型,它和下面的offsetof宏不同。

第二句話:用member的地址減去member在type中的偏移,就得到了包含這個member的type的首地址。

 

offsetof宏定義在[include/linux/stddef.h]中:

#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

 

這裏的技巧是假定有一個在0地址的TYPE類型指針,那麼將它的MEMBER地址獲得,並轉爲size_t(int)類型,這就是MEMBER的偏移了。很巧妙的思路。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章