小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

container_of這個(gè)宏

 lchjczw 2012-12-14

一. 內(nèi)核中大量使用container_of這個(gè)宏,用以進(jìn)行數(shù)據(jù)結(jié)構(gòu)的向上轉(zhuǎn)換,比如這樣一段代碼:

static int platform_match(struct device * dev, struct device_driver * drv)

{

     struct platform_device *pdev = container_of(dev, struct platform_device, dev);

 

     return (strncmp(pdev->name, drv->name, BUS_ID_SIZE) == 0);

}

在這里struct platform_device定義為:

struct platform_device {

     const char    * name;

     u32      id;

     struct device dev;

     u32      num_resources;

     struct resource    * resource;

};

注意,在這個(gè)結(jié)構(gòu)體里面包含了 一個(gè)叫device的結(jié)構(gòu)體,可以將struct platform_device稱(chēng)為父結(jié)構(gòu)體,將struct device稱(chēng)為子結(jié)構(gòu)體。

在上述函數(shù)中,傳遞進(jìn)來(lái)的dev指針將指向platform_device這個(gè)父結(jié)構(gòu)體中的dev成員,而contianer_of這個(gè)宏的作用則在于通過(guò)這個(gè)結(jié)構(gòu)體成員的指針 獲得其父結(jié)構(gòu)體的指針,在這里就是platform_device這一結(jié)構(gòu)體的指針。

要達(dá)到這一目的很容易,只要將 這個(gè)成員的指針減去此成員在整個(gè)結(jié)構(gòu)體內(nèi)的偏移量自然就可以了。看看container_of的定義:

/**

 * container_of - cast a member of a structure out to the containing structure

 * @ptr: the pointer to the member.

 * @type: the type of the container struct this is embedded in.

 * @member:   the name of the member within the struct.

 *

 */

#define container_of(ptr, type, member) ({              \

     const typeof( ((type *)0)->member ) *__mptr = (ptr);    \

     (type *)( (char *)__mptr - offsetof(type,member) );})

這個(gè)宏定義的第一行構(gòu)建一個(gè)叫__mptr的臨時(shí)變量,實(shí)際上并不是必須的,它的作用只是強(qiáng)制編譯器對(duì)數(shù)據(jù)類(lèi)型進(jìn)行檢查。第二行里面的__mptr實(shí)際就是子結(jié)構(gòu)體成員的指針。

偏移量的計(jì)算由offsetof宏完成:

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

這種方法到處都在用,沒(méi)什么新 奇的。


二.  應(yīng)用舉例:

#define list_entry(ptr, type, member)                         \
    container_of(ptr, type, member)

#define list_for_each_entry(pos, head, member)                \
    for (pos = list_entry((head)->next, typeof(*pos), member);\
     prefetch(pos->member.next), &pos->member != (head);      \
     pos = list_entry(pos->member.next, typeof(*pos), member))
//-------------------------------------------------------------
list_entry((head)->next, typeof(*pos), member)返回(head)->next物理指針?biāo)幬恢孟蚯皽p去offsetof()個(gè)字節(jié)數(shù)據(jù)之后, 其父變量pos的物理地址,父變量的類(lèi)型在編譯時(shí)由 typeof(*pos)自 動(dòng)返回(gliethttp).
所以list_for_each_entry遍歷head下面掛接的類(lèi)型為typeof(*pos)的childs結(jié)構(gòu) 體們,當(dāng)然每個(gè)child結(jié)構(gòu)體包含struct list_head nod
de>




三.  container_of(pointer,container_type,container_field);
這個(gè)宏需要一個(gè)container_field字段的指針,該字段包含在container_type類(lèi)型的結(jié)構(gòu)中,然后返回包含該字段的結(jié)構(gòu)指針。
*****************************************
但由于是在驅(qū)動(dòng)中實(shí)現(xiàn)的這個(gè)宏,總不能自己編寫(xiě)一個(gè)驅(qū)動(dòng)來(lái)測(cè)試這個(gè)宏吧(目前的水平而言,編寫(xiě)一個(gè)驅(qū)動(dòng)還是比較費(fèi)勁哦),有沒(méi)有辦法在用戶空間測(cè)試呢?有 的。我們可以將linux/kernel.h頭文件包含進(jìn)來(lái),直接在用戶空間測(cè)試這個(gè)宏的巧妙之處。下面就是我的測(cè)試代碼。
main.c文件
#include <linux/unistd.h>
#include <linux/string.h>
#include <linux/stdlib.h>
#include <linux/kernel.h>

struct cona_t{
    int i;
    int j;
    int v;
    char t[10];
    unsigned short xy;
};


struct cona_t ct;
unsigned short xy;
int main(int argc,char * argv[])
{
    int xy;
    struct cona_t * p;
    memset(&ct,0,sizeof(struct cona_t));
    ct.i = ct.j = ct.v = 10;
    sprintf(ct.t,"%s","sdf");
    ct.xy = 20;
    p = container_of(&ct.xy,struct cona_t,xy);
   
    printf("%s\n",p->t);
    return 0;
}

下面是Makefile文件
CC=gcc
TAR=main
SRC=main.c
KERNEL_INCLUDE ?= /lib/modules/$(shell uname -r)/build/include
all:
    $(CC) -D__KERNEL__ -o $(TAR) -I$(KERNEL_INCLUDE) $(SRC)

clean:
    rm -f $(TAR)
看看一下結(jié)果吧。是不是正好得到了我們想要的東西?
如果打開(kāi)kernel.h文件,就會(huì)發(fā)現(xiàn)這個(gè)container_of這個(gè)宏定義如下:
#define container_of(ptr, type, member) ({            \
        const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
        (type *)( (char *)__mptr - offsetof(type,member) );})

offsetof又被如下定義:
#ifdef __KERNEL__
#undef offsetof
#ifdef __compiler_offsetof
#define offsetof(TYPE,MEMBER) __compiler_offsetof(TYPE,MEMBER)
#else
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#endif

那個(gè)__com

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類(lèi)似文章 更多