亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 服務(wù)器 > Linux服務(wù)器 > 正文

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

2024-09-05 23:05:34
字體:
供稿:網(wǎng)友

1、前面說的

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

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

android7.1/kernel/drivers/inputkernel/drivers/input$ grep -rn container_of ./|wc -l710android7.1/kernel/drivers/input$ 

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

2、container_of的作用

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

內(nèi)核函數(shù)調(diào)用常常給函數(shù)傳入的是結(jié)構(gòu)體成員地址,然后在函數(shù)里面又想使用這個(gè)結(jié)構(gòu)體里面的其他成員變量,所以就引發(fā)了這樣的問題,我認(rèn)為這個(gè)也是用C實(shí)現(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 里面的一個(gè)成員,通過這個(gè)成員的地址獲取sensor_private_data結(jié)構(gòu)體變量的地址,從而調(diào)用里面的成員變量client。這個(gè)方法非常優(yōu)雅。在這里我用到了一個(gè)比較叼的詞,叫“優(yōu)雅”。

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

3、如何使用container_of

container_of需要傳入三個(gè)參數(shù),第一個(gè)參數(shù)是一個(gè)指針,第二個(gè)參數(shù)是結(jié)構(gòu)體類型,第三個(gè)是對(duì)應(yīng)第二個(gè)參數(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里面一定要有這個(gè)成員,不能瞎搞啊
  • 返回結(jié)構(gòu)體的首地址

Linux,內(nèi)核宏,container_of

4、container_of 用到的知識(shí)點(diǎn) 剖析

4.1、({})的作用

({})、第一個(gè)先說這個(gè)表達(dá)式,很多人可能懂,可能在很多地方見到這個(gè)表達(dá)式,但是自己卻沒有注意,這個(gè)表達(dá)式返回最后一個(gè)表達(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獲取變量的類型

這個(gè)我們很少看到,這個(gè)關(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)該都用過吧,比如我想用尺子量一本書本的長(zhǎng)度,我們第一時(shí)間就需要找到尺子的0刻度的位置,然后用這個(gè)0刻度的位置去對(duì)準(zhǔn)書本的邊,然后再貼合對(duì)齊,在書本的另一邊查看尺子刻度就可以知道書本的長(zhǎng)度了。

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

但是在C語言里什么事尺子呢?你想到的可能是sizeof,不幸的是,這個(gè)并不能滿足我們的需要,所以才有了(struct st *),這個(gè)當(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

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

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

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

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

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

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

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

這文章寫了有幾天了,但是一直不想直接發(fā)出去,因?yàn)槲矣X得這個(gè)核心點(diǎn)總是沒有找到一個(gè)特別好的論證方法,看完上面后,大概對(duì)這種測(cè)量應(yīng)該有點(diǎn)感覺了吧,如果現(xiàn)在需要你把一個(gè)數(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位置呢?目前我還沒有找到其他更好的辦法,如果有好的建議的,請(qǐng)留言給我。

4.4、offsetof(TYPE, MEMBER)

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

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

4.5、const int* p的作用

上面的宏定義里面還有一個(gè)小知識(shí)點(diǎn)

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

上面的代碼可以簡(jiǎn)寫成

const int * __mptr

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

這就涉及到兩外兩個(gè)知識(shí)

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

5、 container_of 剖析

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

#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;//用這個(gè)來舉例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);//第一句解析完,實(shí)際上就是獲取a的地址。(type *)( (char *)__mptr - offsetof(type,member) );//這個(gè)變成(struct st *)( (char *)__mptr - ((unsigned int) &((struct st*)0)->a));//這句的意思,把a(bǔ)的地址減去a對(duì)結(jié)構(gòu)體的偏移地址長(zhǎng)度,那就是結(jié)構(gòu)體的地址位置了。

6、實(shí)例代碼

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

代碼如下:

#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 成員變量,跟指針對(duì)應(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é)

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)VEVB武林網(wǎng)的支持。


注:相關(guān)教程知識(shí)閱讀請(qǐng)移步到服務(wù)器教程頻道。
發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
欧美日韩视频免费看| 欧美国产激情一区二区三区蜜月| 国产福利91精品一区| 国产免费一区二区三区最新6| 天天干天天干天天干天天干天天干| 男女网站在线观看| 精品国产凹凸成av人导航| 午夜精品福利久久久| 午夜av不卡| 经典三级在线| 精品国产一区二区亚洲人成毛片| 免费福利视频网站| 97香蕉超级碰碰久久免费的优势| 91精品国产品国语在线不卡| 山东少妇露脸刺激对白在线| 亚洲精品字幕在线| 野花社区视频在线观看| 另类亚洲自拍| 日韩欧美三级电影| 国产美女精彩久久| 欧美video巨大粗暴18| 99国产精品久久久久久久久久久| 欧美性做爰毛片| 美女胸又www又黄的网站| 国产小视频免费| 97操在线视频| 2023国产精品久久久精品双| 男人操女人视频网站| 国产噜噜噜噜久久久久久久久| 免费一区二区三区四区| 丁香婷婷久久久综合精品国产| 91视频一区| 国产精品一区二区久激情瑜伽| 丁香五六月婷婷久久激情| 欧美xxxxx精品| 久久久久久香蕉| 免费a级毛片在线观看| 美女精品一区二区| 精品96久久久久久中文字幕无| 久久精品99国产精品日本| 国产午夜免费福利| 亚洲综合日韩中文字幕v在线| bbw丰满大肥奶肥婆| 欧美激情一区二区三区在线| 国产v片在线观看| 亚洲黄一区二区三区| 国产精品三级在线观看| 国产伦精品一区二区三区在线观看| 在线观看av资源网| 久草.com| 亚洲国产欧美日韩精品| 日韩精品视频免费播放| 亚洲婷婷综合色高清在线| 蜜桃视频m3u8在线观看| 在线亚洲成人| av第一福利大全导航| 久久福利精品| 欧美日韩免费视频| 影音先锋欧美激情| 超碰97国产在线| 亚洲久久成人| 一区二区三区免费| 中文字幕第50页| 欧美日韩一区在线观看视频| 最近2019免费中文字幕视频三| 成人不卡免费视频| 啦啦啦在线视频免费观看高清中文| 中日韩免费视频中文字幕| 人妻少妇精品无码专区久久| 日韩亚洲欧美一区| 国产精品美女无圣光视频| 国产精品进线69影院| 免费黄色网址在线| 国产精品jvid在线观看| 亚洲国产精品毛片| 精品日产乱码久久久久久仙踪林| 国产精品美女午夜爽爽| 日本黑人久久| 无码人妻精品一区二区| 99视频都是精品热在线播放| 高清欧美性猛交| 忘忧草在线日韩www影院| 97超碰在线免费| 午夜激情影院| 成人av综合在线| 国产无遮挡又黄又爽| 91在线观看免费网站| 成人免费看片98欧美| freemovies性欧美| 曰本大片免费观看视频| 三级网站在线看| 深爱五月综合网| 看欧美ab黄色大片视频免费| 欧美日韩黑人| 精品日韩一区二区| 久久电影在线| 久一区二区三区| 久久免费高清| 久久国产人妖系列| 精品丝袜在线| 3atv一区二区三区| 一区二区三区免费看视频| 亚洲欧美日韩直播| 日韩aⅴ视频一区二区三区| 日本一本在线观看| 亚洲成人五区| 亚洲狠狠丁香婷婷综合久久久| 116极品美女视频在线观看| 欧美日韩裸体免费视频| 免费精品一区二区三区在线观看| 91麻豆精品国产91久久久久久久久| 欧美日韩色视频| 欧美区二区三区| 欧美成人xxxx| 久久久久美女| av资源新版天堂在线| 97婷婷大伊香蕉精品视频| 视频一区二区在线观看| 午夜精品久久99蜜桃的功能介绍| 亚洲人免费短视频| 欧美不卡视频一区发布| 久青草国产在线| 欧美在线视频一区二区三区| 亚洲精品高潮| 精品国产青草久久久久福利| 久久国产精品久久精品国产| 国内偷自视频区视频综合| 视频在线这里都是精品| 亚洲国产精品第一区二区| 久久久久99精品成人| 一级黄色免费视频| 精品国产青草久久久久福利| 国产在线观看a| 春意影院免费入口| 日本在线一二三区| 亚洲www永久成人夜色| 国产精品亚洲综合久久小说| av资源站一区| 亚洲人成电影网站色www| 深夜福利av| 91久久线看在观草草青青| 4438x全国最大成人| 欧美国产大片| 欧美性猛交xxxx乱大交91| 欧美激情成人动漫| 日本综合在线观看| av在线网站免费观看| 免费在线观看视频一区| 欧美第一黄网| av影院在线播放| 国产精品21p| 国产午夜视频在线| 亚洲AV无码久久精品国产一区| 免费观看美女裸体网站| 精品中文字幕一区二区三区四区| 美女国产一区二区| 十大免费污污软件| 国产一区二区三区蝌蚪| 天堂在线中文视频| 久久久精品网| 日韩免费毛片| 日韩视频永久免费| 欧美国产精品日韩| 精品婷婷色一区二区三区蜜桃| 麻豆传媒一区二区三区| 日韩欧美国产视频| 青草av.久久免费一区| 一本色道久久88亚洲精品综合| 国产欧美综合一区二区三区| 一本一本久久a久久精品综合麻豆| 日本婷婷久久久久久久久一区二区| 国产精品第十页| 亚洲国产一区二区在线观看| 91影院在线免费观看视频| 亚洲综合视频在线观看| 国产精品99久久免费| 亚洲第一av网站| 噼里啪啦国语在线观看免费版高清版| 中文字幕免费高清在线观看| 成人自拍视频在线观看| 激情综合网五月| 国产精品国产三级国产传播| 国产精品7m凸凹视频分类| 亚洲精品第一国产综合野草社区| 波多野吉衣中文字幕| 日本五十路在线| 亚洲爱爱爱爱爱| 色网站在线视频| 欧美污在线观看| 国产精品igao网网址不卡| 亚洲mv在线看| 韩国三级丰满少妇高潮| 欧美男男tv网站在线播放| 欧美精品精品精品精品免费| 成人黄色在线看| 国产精品第100页| 久草福利资源在线观看| 日本特黄一级片| 成人爽a毛片免费啪啪动漫| 卡一卡二国产精品| 日韩精品一区二区亚洲av性色| 国产麻豆乱码精品一区二区三区| 日韩视频免费看| 国产91精品入口17c| www.五月婷婷.com| 伊人久久大香伊蕉在人线观看热v| 国产1区2区3区4区| 一级毛片免费高清中文字幕久久网| 精品国产第一国产综合精品| 麻豆一区一区三区四区| 无码人妻av一区二区三区波多野| 99爱精品视频| 国内精品**久久毛片app| 亚洲第一区视频| 88av在线播放| 霍思燕三级露全乳照| 久久五月天综合| 亚洲精品黄色| 亚洲成人av资源| 欧美粗暴jizz性欧美20| 麻豆精品视频在线| 亚洲一区二区精品在线| 日韩欧美久久| 久久99久久亚洲国产| 欧美xfplay| 小早川怜子影音先锋在线观看| 国产一区二区三区奇米久涩| 老司机在线视频二区| 成人综合专区| 国产欧美一区二区三区鸳鸯浴| 中文字幕欧美日韩久久| 一区二区三区四区高清精品免费观看| 蜜桃传媒麻豆第一区在线观看| 香蕉久久aⅴ一区二区三区| 免费国偷自产拍精品视频| 亚洲国产精品免费在线观看| 成人国产精品毛片| 亚洲视频一二三| 中文成人激情娱乐网| 人人澡人人澡人人看| 爱情岛论坛亚洲首页入口章节| 99久久99精品久久久久久| 欧美黄视频在线观看| www.久久av| 国产中文一区二区三区| 日本少妇毛茸茸| 视频二区不卡| 日韩xxxx视频| 国产做受69高潮| 亚洲国产欧美一区二区丝袜黑人| 韩日成人av| 中文字幕第一区第二区| 亚洲国产视频一区| 久久精视频免费在线久久完整在线看| 黄色电影在线免费观看| 制服丝袜第二页| 久久精品五月婷婷| 欧美乱大交xxxxx在线观看| 45www国产精品网站| 亚洲精品有码在线| 中文字幕av久久爽一区| 91精品国产成人观看| 日韩欧美精品网址| 欧美视频一区在线观看| 北条麻妃av毛片免费观看| 久久久av网站| 九色在线视频| 成人av毛片在线观看| 国产叼嘿视频在线观看| 免费91麻豆精品国产自产在线观看| 很黄很黄的网站免费的| 51精品久久久久久久蜜臀| av地址在线观看| 波多野结衣视频播放| 亚洲小少妇裸体bbw| 久久国产精品精品国产色婷婷| 麻豆视频在线观看免费| 亚洲视频在线二区| 亚洲色图27p| 成人av中文| 免费在线播放第一区高清av| 精品国产aⅴ一区二区三区东京热| 波兰性xxxxx极品hd| 亚洲aⅴ日韩av电影在线观看| 精品视频一二三| 久久九九热视频| 久久综合国产精品台湾中文娱乐网| 国产精品美女久久久久人| 蜜桃久久久久| 欧美视频日韩视频在线观看| 91九色综合久久| jizz欧美大全| 欧美福利视频导航| 欧美高清dvd| 国产片在线观看| 好操啊在线观看免费视频| 欧美日韩午夜影院| 六月婷婷中文字幕| 伊人久久99| 国产又粗又黄又爽的视频| 欧美精品九九99久久| 色播在线视频| 亚洲一区二区三区黄色| 成人看片在线观看| 久久艹免费视频| 日本一区二区三级电影在线观看| 我要看一级黄色大片| 欧美日韩亚洲一区二区三区在线观看| 中文字幕一区在线播放| 神马久久影院| 99国产精品久久| 免费精品视频一区二区三区| 国产美女久久久久久| 国产成人免费观看视频| 影音先锋电影在线观看| 在线观看国产三级| 中文字幕亚洲综合久久菠萝蜜| 欧美色中文字幕| 亚洲人成在线网站| 欧美日韩亚洲网| 中文一区二区三区四区| 亚洲国产精品久久| 99精品热视频| 91在线成人| 亚洲人挤奶视频| 99在线看视频| 中文字幕 91| 亚洲欧美在线aaa|