new linux device driver - container_of

offset_of

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


先把 0 強迫轉型為存放 TYPE 資料的起始位置, 然後指到 MEMBER, 取出 MEMBER 位置.
因為起始位置為 0, 該 MEMBER 取出的位置 即為 offset


container_of

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


只要知道一個資料結構內欄位的指標, 就可以得到這個資料結構的起始位置

    container_of(pointer, container_type, container_field);

範例

container_of example - github


struct dog {
 char *name;
};

struct cat {
 char *name;
};

struct mypets {
 struct dog mydog;
 struct cat mycat;
} mp;


static int __init hello_init(void)
{
 struct mypets *whospets;
 struct cat *mc;

 mp.mydog.name = "SnowDragon";
 mp.mycat.name = "Flower";
 mc = &mp.mycat;
 whospets = container_of(mc, struct mypets, mycat);
 pr_info("my dog's name: %s\n", whospets->mydog.name);
 return 0;
}


譬如我們有個 型態 mypets, 裡面有 mydog / mycat 欄位
如果我們知道 mycat 欄位指標 mc, 
我們可以透過 container_of, 找到有含這個 mc , 型態為 struct mypets, 欄位為 mycat, 
的整個 data structure 

 whospets = container_of(mc, struct mypets, mycat);


--
執行結果: 

my dog's name: SnowDragon





留言

熱門文章