婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av

主頁 > 知識庫 > Linux內(nèi)核宏container_of的深度剖析

Linux內(nèi)核宏container_of的深度剖析

熱門標(biāo)簽:申請400電話價格多少 云會外呼系統(tǒng) 涪陵商都400電話開通辦理 智能電話機(jī)器人坐席 外呼系統(tǒng)不彈窗 外呼系統(tǒng)的經(jīng)營范圍 柳州市機(jī)器人外呼系統(tǒng)報價 廈門營銷外呼系統(tǒng)平臺 安陽ai電銷機(jī)器人軟件

1、前面說的

我在好幾年前讀linux 驅(qū)動代碼的時候看到這個宏,百度了好久,知道怎么用了,但是對實現(xiàn)過程和原理還是一知半解。

container_of宏 在linux內(nèi)核代碼里面使用次數(shù)非常非常多,對于喜歡linux編程的同學(xué)來說,了解其實現(xiàn)方法,對以后看內(nèi)核代碼,寫內(nèi)核驅(qū)動的幫助都非常大,當(dāng)然,我不是說了解這個就可以為所欲為了,內(nèi)核博大精深,先宏觀再微觀去學(xué)習(xí),不積跬步何以致千里,不要想著一口就能吃成一個胖子,我這篇文章主要剖析一下這個函數(shù)的實現(xiàn)原理,希望對大家學(xué)習(xí)過程中有所幫助。

android7.1/kernel/drivers/input
kernel/drivers/input$ grep -rn container_of ./|wc -l
710
android7.1/kernel/drivers/input$ 

使用grep -rn container_of ./|wc -l統(tǒng)計了下kernel/drivers/input/目錄下的container_of出現(xiàn)的次數(shù),一共有710次使用。

2、container_of的作用

container_of的作用的通過結(jié)構(gòu)體成員變量地址獲取這個結(jié)構(gòu)體的地址,假設(shè)你的名字叫李光明,你還有一個弟弟叫做XXX,警察叔叔發(fā)現(xiàn)你弟弟XXX干了一件壞事,但是警察叔叔不知道你弟弟的名字,抓你來審問,你嘴巴很硬就是不說,警察叔叔就拿到你的名字,查到了你家的戶口本,這下你弟弟就被查出來了,原來你弟弟XXX的名字叫做李小明。這種破案手法叫做順藤摸瓜。

內(nèi)核函數(shù)調(diào)用常常給函數(shù)傳入的是結(jié)構(gòu)體成員地址,然后在函數(shù)里面又想使用這個結(jié)構(gòu)體里面的其他成員變量,所以就引發(fā)了這樣的問題,我認(rèn)為這個也是用C實現(xiàn)面向?qū)ο缶幊痰囊环N方法。

比如這段代碼

static void sensor_suspend(struct early_suspend *h)          
{                          
  struct sensor_private_data *sensor =               
      container_of(h, struct sensor_private_data, early_suspend);  
  if (sensor->ops->suspend)                     
    sensor->ops->suspend(sensor->client);             
} 

early_suspend是sensor_private_data 里面的一個成員,通過這個成員的地址獲取sensor_private_data結(jié)構(gòu)體變量的地址,從而調(diào)用里面的成員變量client。這個方法非常優(yōu)雅。在這里我用到了一個比較叼的詞,叫“優(yōu)雅”。

這里簡單說下,傳進(jìn)來的h一定在其他地方定義并且操作系統(tǒng)分配了內(nèi)存空間,h分配了空間,說明他的老爸也有內(nèi)存了,要不然你順藤摸瓜摸到一個NULL就傻逼了。

3、如何使用container_of

container_of需要傳入三個參數(shù),第一個參數(shù)是一個指針,第二個參數(shù)是結(jié)構(gòu)體類型,第三個是對應(yīng)第二個參數(shù)里面的結(jié)構(gòu)體里面的成員。

container_of(ptr, type, member)

  • ptr:表示結(jié)構(gòu)體中member的地址 h
  • type:表示結(jié)構(gòu)體類型 struct sensor_private_data
  • member:表示結(jié)構(gòu)體中的成員 early_suspend type里面一定要有這個成員,不能瞎搞啊
  • 返回結(jié)構(gòu)體的首地址

4、container_of 用到的知識點 剖析

4.1、({})的作用

({})、第一個先說這個表達(dá)式,很多人可能懂,可能在很多地方見到這個表達(dá)式,但是自己卻沒有注意,這個表達(dá)式返回最后一個表達(dá)式的值。比如x=({a;b;c;d;}),最終x的值應(yīng)該是d。

代碼例子:

#include<stdio.h>
void main(void)
{
  int a=({1;2;4;})+10;
  printf("%d\n",a);//a=14
}

4.2、typeof獲取變量的類型

這個我們很少看到,這個關(guān)鍵字是C語言關(guān)鍵字的拓展,返回變量的類型,具體可以看GCC里面的介紹
https://gcc.gnu.org/onlinedocs/gcc/Typeof.html

++Another way to refer to the type of an expression is with typeof. The syntax of using of this keyword looks like sizeof, but the construct acts semantically like a type name defined with typedef.++

代碼例子:

void main(void)
{
  int a = 6;
  typeof(a) b =9;
  printf("%d %d\n",a,b);
}

4.3、(struct st*)0的作用

尺子大家應(yīng)該都用過吧,比如我想用尺子量一本書本的長度,我們第一時間就需要找到尺子的0刻度的位置,然后用這個0刻度的位置去對準(zhǔn)書本的邊,然后再貼合對齊,在書本的另一邊查看尺子刻度就可以知道書本的長度了。

現(xiàn)在我們需要量一個結(jié)構(gòu)體的長度,我們也可以用尺子來量,我們只要找到這個0刻度的位置就可以了。同理,即使我們不知道0刻度位置,我們首尾刻度相減一樣可以計算出結(jié)構(gòu)體的長度。

但是在C語言里什么事尺子呢?你想到的可能是sizeof,不幸的是,這個并不能滿足我們的需要,所以才有了(struct st *),這個當(dāng)作尺子真的再好不過了。

struct st{
  int a;
  int b;
}*p_st,n_st;
void main(void)
{
  printf("%p\n",&((struct st*)0)->b);
}

上面的代碼

(struct st*)0

這個的意思就是把這個結(jié)構(gòu)體放到0刻度上面開始量了,然后量到哪里呢?

&((struct st*)0)->b)

這個就體現(xiàn)出來了,量到b的位置。所以上面的輸出應(yīng)該是4。

看完上面的解釋,應(yīng)該知道下面這兩個代碼的功能是一樣的。

typeof ((struct st*)0)->b) c; // 取b的類型來聲明c
int c;

其實不只是對于0,用其他數(shù)字一樣是有效的,比如下面的代碼,編譯器關(guān)心的是類型,而不在乎這個數(shù)字。

printf("%p\n",&((struct st*)4)->b -4 );

這文章寫了有幾天了,但是一直不想直接發(fā)出去,因為我覺得這個核心點總是沒有找到一個特別好的論證方法,看完上面后,大概對這種測量應(yīng)該有點感覺了吧,如果現(xiàn)在需要你把一個數(shù)組的首地址設(shè)置為0,要怎么做呢?

先思考一下,假設(shè)這里延遲了幾分鐘。

代碼如下:

struct A {
  short array[100];
};
int main(int argc, char *argv[])
{
  int i = 10;
  A* a = (A*)0;
  printf("%p %d %d\n",a,sizeof(short), &a->array[20]);
  getchar();
  return 1;
}
//輸出 00000000 2 40

有什么辦法不使用==struct A *== 直接把數(shù)組的地址放到0位置呢?目前我還沒有找到其他更好的辦法,如果有好的建議的,請留言給我。

4.4、offsetof(TYPE, MEMBER)

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

size_t 這個有不懂的可以百度下,就是unsigned 的整數(shù),在32位和64位下長度不同,所以這個offsetof就是獲取結(jié)構(gòu)體的偏移長度。

4.5、const int* p的作用

上面的宏定義里面還有一個小知識點

const typeof( ((type *)0)->member ) *__mptr

上面的代碼可以簡寫成

const int * __mptr

這個說明什么問題呢?這個說明__mptr指向的整型數(shù)據(jù)是一個const(常數(shù))。

這就涉及到兩外兩個知識

int * const __mptr;//表示__mptr的值不能改變
//和
const int * const __mptr; //表示__mptr不能改變而且指向的內(nèi)容也不能改變

5、 container_of 剖析

看完上面的幾個知識點,再來看container_of這個宏就顯得非常清晰了。我把解析部分寫在下面的代碼注釋里面。

#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE*)0)->MEMBER)
#define container_of(ptr, type, member) ({     \

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

    (type *)( (char *)__mptr - offsetof(type,member) );})
//-----分割線
struct st{
  int a;
  int b;
}*pt;
//用這個來舉例
container_of(&pt->a,struct st,a)
 const typeof( ((struct st *)0)->a ) *__mptr = (const typeof( ((struct st *)0)->a ) *)(&pt->a);
const int *__mptr = (int *)(&pt->a);//第一句解析完,實際上就是獲取a的地址。
(type *)( (char *)__mptr - offsetof(type,member) );
//這個變成
(struct st *)( (char *)__mptr - ((unsigned int) &((struct st*)0)->a));
//這句的意思,把a(bǔ)的地址減去a對結(jié)構(gòu)體的偏移地址長度,那就是結(jié)構(gòu)體的地址位置了。

6、實例代碼

經(jīng)過上面的解釋,至少對這個宏有感覺了吧,寫個代碼來測試一下,讓自己與代碼融合為一體,這樣才能做到人碼合一的境界。

代碼如下:

#include<stdio.h>
#include<stddef.h>
#include<stdlib.h>
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE*)0)->MEMBER)
/*ptr 成員指針
* type 結(jié)構(gòu)體 比如struct Stu
* member 成員變量,跟指針對應(yīng)
* */
#define container_of(ptr, type, member) ({     \

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

    (type *)( (char *)__mptr - offsetof(type,member) );})
typedef struct Stu{
    int age;
    char name[10];
    int id;
    unsigned long phone_num;
}*p_stu,str_stu;
void print_all(void *p_str)
{
  p_stu m1p_stu = NULL;
  m1p_stu = container_of(p_str,struct Stu,age);
  printf("age:%d\n",m1p_stu->age);
  printf("name:%s\n",m1p_stu->name);
  printf("id:%d\n",m1p_stu->id);
  printf("phone_num:%d\n",m1p_stu->phone_num);
}
void main(void)
{
  p_stu m_stu = (p_stu)malloc(sizeof(str_stu));
  m_stu->age = 25;
  m_stu->id = 1;
  m_stu->name[0]='w';
  m_stu->name[1]='e';
  m_stu->name[2]='i';
  m_stu->name[3]='q';
  m_stu->name[4]='i';
  m_stu->name[5]='f';
  m_stu->name[6]='a';
  m_stu->name[7]='\0';
  m_stu->phone_num=13267;
  /*傳結(jié)構(gòu)體成員指針進(jìn)去*/
  print_all(&m_stu->age);
  printf("main end\n");
  if(m_stu!=NULL)
    free(m_stu);
}

7、程序輸出

age:25
name:weiqifa
id:1
phone_num:13267
main end

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,謝謝大家對腳本之家的支持。如果你想了解更多相關(guān)內(nèi)容請查看下面相關(guān)鏈接

標(biāo)簽:南充 巴中 孝感 蕪湖 撫順 晉城 綏化 福州

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《Linux內(nèi)核宏container_of的深度剖析》,本文關(guān)鍵詞  Linux,內(nèi)核,宏,container,的,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請?zhí)峁┫嚓P(guān)信息告之我們,我們將及時溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《Linux內(nèi)核宏container_of的深度剖析》相關(guān)的同類信息!
  • 本頁收集關(guān)于Linux內(nèi)核宏container_of的深度剖析的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章
    婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av
    亚洲观看高清完整版在线观看| 亚洲免费观看高清完整版在线观看| 国产女主播一区| 亚洲成人激情av| 国产成人在线免费| 欧美精品精品一区| 国产精品不卡一区二区三区| 久久精工是国产品牌吗| 日本黄色一区二区| 日本一区二区三区免费乱视频| 日精品一区二区三区| 色欧美88888久久久久久影院| 欧美sm美女调教| 日本不卡一区二区三区高清视频| 91一区二区在线| 中文av一区二区| 国产高清不卡二三区| 69av一区二区三区| 偷拍一区二区三区四区| 99在线精品观看| 国产精品久久久久久亚洲毛片| 国产精品夜夜嗨| 国产视频一区二区三区在线观看| 激情国产一区二区| 久久久久亚洲蜜桃| 国产一区二区三区黄视频 | 99精品1区2区| 国产精品看片你懂得| 成人永久看片免费视频天堂| 久久精品夜夜夜夜久久| 韩国毛片一区二区三区| 精品第一国产综合精品aⅴ| 韩国欧美国产1区| 日本一区二区三级电影在线观看 | 国内久久精品视频| 精品人在线二区三区| 久久成人免费网| 久久久久九九视频| 成人一级片在线观看| 国产精品嫩草影院av蜜臀| 97久久精品人人做人人爽50路 | 国产亚洲精品精华液| 国产美女久久久久| 日本一区二区久久| 色偷偷久久人人79超碰人人澡 | 久久国产福利国产秒拍| 久久先锋影音av鲁色资源网| 国产成人在线视频网站| 亚洲国产精品精华液ab| 色视频成人在线观看免| 日韩和的一区二区| 精品剧情在线观看| 国产东北露脸精品视频| 国产精品电影院| 欧美中文字幕一区二区三区亚洲| 香蕉成人伊视频在线观看| 欧美一区二区三区免费大片| 久久精品国产99国产| 国产精品国产三级国产普通话99| 欧美午夜精品理论片a级按摩| 青草av.久久免费一区| 亚洲国产精品精华液2区45| 91福利社在线观看| 国产一区免费电影| 亚洲女同一区二区| 精品久久国产字幕高潮| 毛片一区二区三区| 国产精品福利电影一区二区三区四区| 欧美性淫爽ww久久久久无| 精品伊人久久久久7777人| 亚洲欧洲日本在线| 日韩精品最新网址| 色综合中文综合网| 国产99精品国产| 亚洲午夜久久久久久久久久久 | 91精品国产入口| 国产成人精品综合在线观看| 亚洲综合色成人| 久久久777精品电影网影网 | 国产一区二区视频在线播放| 亚洲精品乱码久久久久久日本蜜臀 | 日韩精品一区二区三区四区视频| 不卡在线视频中文字幕| 日本成人在线看| 亚洲人精品午夜| 久久久亚洲精品一区二区三区| 91久久香蕉国产日韩欧美9色| 韩国精品一区二区| 亚洲成人动漫在线观看| 国产精品污网站| 精品国产乱子伦一区| 欧美亚洲日本国产| 91免费看片在线观看| 国产sm精品调教视频网站| 蜜臀av亚洲一区中文字幕| 亚洲一区二区偷拍精品| 国产精品久久精品日日| 国产日韩高清在线| 久久蜜桃av一区精品变态类天堂 | 麻豆视频一区二区| 首页国产丝袜综合| 五月激情综合色| 亚洲一二三专区| 一区二区三区在线高清| 自拍偷拍国产精品| 一区在线播放视频| 中文字幕一区二区在线播放 | 久久欧美一区二区| 精品剧情v国产在线观看在线| 欧美一区二区视频网站| 欧美精品自拍偷拍| 欧美精品123区| 欧美日韩国产三级| 欧美日韩大陆一区二区| 欧美日韩视频一区二区| 欧美美女一区二区在线观看| 欧美午夜精品久久久久久超碰 | 国产精品女主播av| 一区在线观看视频| 日韩美女视频一区| 怡红院av一区二区三区| 亚洲成人精品一区二区| 日韩精品一二三| 美女爽到高潮91| 国产高清不卡一区二区| 99久久精品久久久久久清纯| 色系网站成人免费| 7777精品伊人久久久大香线蕉的| 欧美一区二区精品久久911| 日韩欧美激情在线| 国产亚洲欧美日韩在线一区| 国产精品久久久久久久午夜片| 国产精品国产三级国产普通话99 | 丝瓜av网站精品一区二区| 久久综合综合久久综合| 国产成人一级电影| 色老汉一区二区三区| 欧美精品日日鲁夜夜添| 欧美精品一区二区三区视频| 日本一区二区三区四区在线视频| 日韩伦理av电影| 五月激情综合网| 国产美女精品一区二区三区| 成人a区在线观看| 欧美写真视频网站| 久久亚洲捆绑美女| 一区二区三区不卡视频在线观看| 日本不卡在线视频| 成人av电影在线播放| 欧美揉bbbbb揉bbbbb| 久久久亚洲午夜电影| 亚洲精品菠萝久久久久久久| 免费成人小视频| 91丨国产丨九色丨pron| 欧美不卡一区二区| 一区二区三区在线观看欧美| 久久成人18免费观看| 欧美性视频一区二区三区| 久久免费午夜影院| 亚洲一二三区在线观看| 国产自产高清不卡| 欧美肥妇bbw| 亚洲视频免费观看| 精品一区二区三区的国产在线播放| 不卡免费追剧大全电视剧网站| 欧美一区永久视频免费观看| 亚洲人成小说网站色在线| 国产美女娇喘av呻吟久久| 欧美日韩国产精品成人| 亚洲欧洲成人精品av97| 久久精品国产成人一区二区三区| 欧美亚洲一区三区| 亚洲色图在线看| 国产成人一区二区精品非洲| 日韩美女在线视频| 日韩在线一区二区| 欧美性猛交xxxx乱大交退制版 | 国产裸体歌舞团一区二区| 在线电影一区二区三区| 一区二区成人在线视频| voyeur盗摄精品| 国产日韩高清在线| 国产精品一区二区视频| 久久久久综合网| 韩国毛片一区二区三区| 日韩美女视频在线| 免费高清不卡av| 日韩欧美国产综合在线一区二区三区| 亚洲综合区在线| 欧美做爰猛烈大尺度电影无法无天| 欧美国产欧美亚州国产日韩mv天天看完整 | 欧美在线综合视频| 亚洲黄色片在线观看| 色婷婷亚洲一区二区三区| 国产精品麻豆网站| 色综合久久88色综合天天6| 亚洲女与黑人做爰| 欧美日免费三级在线| 日本不卡中文字幕| 日韩视频123|