乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      container_of這個宏

       lchjczw 2012-12-14

      一. 內(nèi)核中大量使用container_of這個宏,用以進(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;

      };

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

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

      要達(dá)到這一目的很容易,只要將 這個成員的指針減去此成員在整個結(jié)構(gòu)體內(nèi)的偏移量自然就可以了??纯?/span>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òu)建一個叫__mptr的臨時變量,實(shí)際上并不是必須的,它的作用只是強(qiáng)制編譯器對數(shù)據(jù)類型進(jìn)行檢查。第二行里面的__mptr實(shí)際就是子結(jié)構(gòu)體成員的指針。

      偏移量的計算由offsetof宏完成:

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

      這種方法到處都在用,沒什么新 奇的。


      二.  應(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()個字節(jié)數(shù)據(jù)之后, 其父變量pos的物理地址,父變量的類型在編譯時由 typeof(*pos)自 動返回(gliethttp).
      所以list_for_each_entry遍歷head下面掛接的類型為typeof(*pos)的childs結(jié)構(gòu) 體們,當(dāng)然每個child結(jié)構(gòu)體包含struct list_head nod
      de>




      三.  container_of(pointer,container_type,container_field);
      這個宏需要一個container_field字段的指針,該字段包含在container_type類型的結(jié)構(gòu)中,然后返回包含該字段的結(jié)構(gòu)指針。
      *****************************************
      但由于是在驅(qū)動中實(shí)現(xiàn)的這個宏,總不能自己編寫一個驅(qū)動來測試這個宏吧(目前的水平而言,編寫一個驅(qū)動還是比較費(fèi)勁哦),有沒有辦法在用戶空間測試呢?有 的。我們可以將linux/kernel.h頭文件包含進(jìn)來,直接在用戶空間測試這個宏的巧妙之處。下面就是我的測試代碼。
      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é)果吧。是不是正好得到了我們想要的東西?
      如果打開kernel.h文件,就會發(fā)現(xiàn)這個container_of這個宏定義如下:
      #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

      那個__com

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

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多