日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux中probe函数中传递的参数来源(上)

發布時間:2025/4/16 linux 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux中probe函数中传递的参数来源(上) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

點擊打開鏈接

上一篇中,我們追蹤了probe函數在何時調用,知道了滿足什么條件會調用probe函數,但probe函數中傳遞的參數我們并不知道在何時定義,到底是誰定義的,反正不是我們在驅動中定義的(當然,驅動中也不會定義設備的詳細信息),但也不是在我們設備信息定義時的結構體。這就相當于武林絕學中只打通了任脈,而督脈還沒打通,要想成為武林高手還差一步,本文就致力于打通我們設備驅動probe函數的任督二脈,做到正向逆向全順暢,當任督二脈全都打通后,。。。,就可以獨步武林、指點江山啦,再然后按照武林高手成名后既定的流程,該寂寞地隱去了(好像又再做白日夢了),當然了Linux中值得我們要學的多著呢,除了編寫內核的那幫家伙們偶爾會寂寞下外,我們還是沒有多少時間留給我們寂寞的(^_^)。

???????? 雖然不知道probe函數的參數怎么來的,但沒吃過豬肉,還是見過豬跑的,有點關系就能找到出路。經常聽說:先注冊設備時,內核會將設備信息掛到設備鏈上,然后等待命中注定的有緣的設備驅動mm or gg。so,我們可以猜想:應該是設備注冊的時候,內核將設備信息掛到上面去的,按照這個猜想,我們應該先從設備注冊入手,但是這么多函數到底朝哪個方向努力呀?所以,先從傳遞的參數入手,查看下,等走不通了在去從設備注冊入手,起碼有了努力的方向了。

調用probe函數的是:static int really_probe(struct device *dev, struct device_driver*drv),里面有調用ret = dev->bus->probe(dev)和ret =drv->probe(dev)。函數如下:

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

{

???????? intret = 0;

......

?

???????? if (dev->bus->probe) {

?????????????????? ret = dev->bus->probe(dev);

?????????????????? if (ret)

??????????????????????????? goto probe_failed;

???????? } else if (drv->probe) {

?????????????????? ret = drv->probe(dev);

?????????????????? if (ret)

??????????????????????????? goto probe_failed;

???????? }

?

......

???????? returnret;

}

這里的參數dev是上一個函數傳遞進來的,上一個函數為:int driver_probe_device(struct device_driver *drv, struct device*dev)

int driver_probe_device(structdevice_driver *drv,?struct device *dev)

{

???????? intret = 0;

? ......

?????????ret = really_probe(dev, drv);


......?

???????? returnret;

}

這里的dev又是上一個函數傳遞進來的,上一個函數為:static int __driver_attach(struct device *dev, void *data)

static int __driver_attach(struct device *dev, void *data)

{

???????? structdevice_driver *drv = data;

? ......

???????? device_lock(dev);

???????? if(!dev->driver)

?????????????????? driver_probe_device(drv, dev);

???????? device_unlock(dev);

? ? ? ? ......

???????? return0;

}

這里的dev又是上一個函數傳遞進來的,調用__driver_attach的函數為:int driver_attach(struct device_driver *drv),但本函數沒有給__driver_attach傳遞參數。

int driver_attach(structdevice_driver *drv)

{

???????? returnbus_for_each_dev(drv->bus, NULL, drv,__driver_attach);

}

???????? 這里面調用了__driver_attach,對應error =fn(dev, data)。第一個參數dev為while ((dev = next_device(&i)) && !error)產生。即dev有i間接產生。

int bus_for_each_dev(struct bus_type *bus, struct device *start,

?????????????????? ???? void *data, int (*fn)(struct device *,void *))

{

???????? structklist_iter i;

???????? structdevice *dev;

???????? interror = 0;

....

?

???????? klist_iter_init_node(&bus->p->klist_devices, &i,

??????????????????????????? ???? (start ? &start->p->knode_bus :NULL));

?????????while ((dev = next_device(&i)) && !error)

???????????????????error = fn(dev, data);

???????? klist_iter_exit(&i);

???????? returnerror;

}

之所以是next_device(&i),因為第一個節點為頭節點,需要從下一個開始,先看看klist_iter_init_node(&bus->p->klist_devices, &i, (start ? &start->p->knode_bus : NULL))對i干了什么?因為start為NULL,故傳遞的第三個參數n為NULL。

void klist_iter_init_node(struct klist *k,struct klist_iter *i,

??????????????????????????? ? struct klist_node *n)

{

???????? i->i_klist= k;

???????? i->i_cur= n;

???????? if(n)

?????????????????? kref_get(&n->n_ref);

}

???????? 看來ta沒干什么,就是賦了兩個值。然后再看最重要的next_device(&i)

static struct device *next_device(struct klist_iter *i)

{

???????? structklist_node *n = klist_next(i);

???????? structdevice *dev = NULL;

???????? structdevice_private *p;

?

???????? if(n) {

???????????????????p = to_device_private_parent(n);

?????????????????? dev = p->device;

???????? }

???????? returndev;

}

#define to_device_private_parent(obj)? \

???????? container_of(obj,struct device_private, knode_parent)

???????? 看到dev由p->device賦值,p為struct device_private,n = i->i_cur為structklist_node 型(后面分析)。為了看懂這個函數,需要補充N多知識,先上幾個struct:

struct klist_iter {

???????? structklist???????????????? *i_klist;

???????? structklist_node????? *i_cur;

};

?

struct klist {

???????? spinlock_t????????????????? k_lock;

???????? structlist_head??????? k_list;

???????? void??????????????????? (*get)(struct klist_node *);

???????? void??????????????????? (*put)(struct klist_node *);

} __attribute__ ((aligned (sizeof(void*))));

?

struct klist_node {

???????? void??????????????????? *n_klist;?? /* never access directly */

???????? structlist_head??????? n_node;

???????? structkref????????????????? n_ref;

};

?

struct kref {

???????? atomic_trefcount;

};

?

? ? ? ? ?其中的klist_iter_init_node(&bus->p->klist_devices, &i,(start ?&start->p->knode_bus :?NULL))作用是定義個klist_iter指向此klist,以便以后直接使用,如圖:

?

???????? 再把關鍵的函數拷到此處,以遍分析:

?????????while ((dev = next_device(&i)) && !error)

???????????????????error = fn(dev, data);

static struct device *next_device(struct klist_iter *i)

{

???????? structklist_node *n = klist_next(i);

???????? structdevice *dev = NULL;

???????? structdevice_private *p;

?

???????? if(n) {

???????????????????p = to_device_private_parent(n);

?????????????????? dev = p->device;

???????? }

???????? returndev;

}

?

/**

?*klist_next - Ante up next node in list.

?*@i: Iterator structure.

?*

?*First grab list lock. Decrement the reference count of the previous

?*node, if there was one. Grab the next node, increment its reference

?*count, drop the lock, and return that next node.

?*/

struct klist_node *klist_next(struct klist_iter *i)

{

???????? void(*put)(struct klist_node *) = i->i_klist->put;

???????? structklist_node *last = i->i_cur;//NULL

???????? structklist_node *next;

?

???????? spin_lock(&i->i_klist->k_lock);

?

???????? if(last) {

?????????????????? next= to_klist_node(last->n_node.next);

?????????????????? if(!klist_dec_and_del(last))

??????????????????????????? put= NULL;

???????? }else

???????????????????next= to_klist_node(i->i_klist->k_list.next);

?

???????? i->i_cur= NULL;

???????? while(next != to_klist_node(&i->i_klist->k_list)){

?????????????????? if(likely(!knode_dead(next))) {

??????????????????????????? kref_get(&next->n_ref);

????????????????????????????i->i_cur = next;

??????????????????????????? break;

?????????????????? }

?????????????????? next= to_klist_node(next->n_node.next);

???????? }

?

???????? spin_unlock(&i->i_klist->k_lock);

?

???????? if(put && last)

?????????????????? put(last);

???????? returni->i_cur;

}

???????? 這里last =i->i_cur;為NULL,然后執行next = to_klist_node(i->i_klist->k_list.next);從這個函數來看,就是取出了包含i->i_klist->k_list.next的n_node指針。不過next所指的和n_node地址偏差一個head指針(list_head包括head和next倆指針)。while循環是從第一個目標to_klist_node(i->i_klist->k_list.next)循環,當再次循環到頭節點to_klist_node(&i->i_klist->k_list)時截止(這是個循環鏈表,總會再次循環回來的)。還一個結束的條件,當循環到knode_dead(next)為真時break,不過,likely說明了next通常不會是dead的,(struct klist_node的第一個成員最后一位做標志dead位,網上還說有指針的作用,我覺得好像做了標志位了就不能做指向頭節點的指針了,不過void *n_klist名字起得確實很有迷惑性)。

static struct klist_node*to_klist_node(struct list_head *n)

{

???????? returncontainer_of(n, struct klist_node, n_node);

}

???????? 還一個i的來源,ta是一切的來源。在klist_iter_init_node(&bus->p->klist_devices,&i, ???????????????????????? ?????(start ? &start->p->knode_bus :NULL))中,?????? i->i_klist = &bus->p->klist_devices;i->i_cur = NULL;

?

???????? Klist_iter找到合適的即停止搜索,找到此處的device_private的device,此結構即為傳入probe函數的參數。device源于i(i只是暫時用于查找定義的一個臨時變量),而i源于bus,bus源于drv->bus,drv源于sdrv->driver,sdrv即為mx25lx_driver,不過mx25lx_driver->driver中的bus,只給賦了一個值,而在后來調用標準的spi函數時,又重新對bus賦了值spi_bus_type,spi_bus_type是spi.c中的struct bus_type定義的全局變量。


總結

以上是生活随笔為你收集整理的linux中probe函数中传递的参数来源(上)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 一区二区高清在线观看 | 国产无遮挡裸体免费视频 | 久在线视频 | 欧美日韩在线影院 | 96在线观看| 中文精品久久久久人妻不卡 | 福利视频亚洲 | 亚洲AV午夜精品 | 精品国产综合 | 啪啪av导航 | 日本精品久久久久中文字幕 | 欧美黑人性受xxxx精品 | 亚洲啊v在线 | 久久久夜精品 | 亚洲色欧美另类 | 黄色小视频免费观看 | av在线播放观看 | 中文字幕免费在线观看视频 | 伊人免费视频二 | 理论片大全免费理伦片 | 亚洲av日韩av高潮潮喷无码 | 秋霞电影网一区二区 | 九色综合网 | 国产亚洲色婷婷久久99精品 | 另类综合小说 | 成人日b视频 | 中文毛片无遮挡高潮免费 | 美女被草 | 99热9| 影音先锋在线观看视频 | 播放男人添女人下边视频 | 色人阁av | 涩涩涩涩涩涩涩涩涩 | 亚洲字幕av一区二区三区四区 | 国产拍拍拍 | 少妇激情偷人爽爽91嫩草 | 久久久涩 | 国产日韩激情 | 日韩精品中文字幕在线播放 | 在线免费精品视频 | 丰满少妇毛片 | 操极品美女 | 爱爱动态图 | 天天干b| 99精品免费视频 | 亚洲国产网址 | h片在线免费观看 | 69视频一区二区 | 亚洲午夜精品福利 | 天天天操 | 性色一区 | 日本韩国毛片 | 夜夜嗨aⅴ一区二区三区 | 一边吃奶一边摸做爽视频 | 日韩少妇裸体做爰视频 | 成人黄色国产 | 国产这里只有精品 | 黑人精品无码一区二区三区AV | 在线观看免费成人 | 欧美激情亚洲色图 | 风流还珠之乱淫h文 | www.成人国产 | 禁久久精品乱码 | 亚洲综合色吧 | 91爱国产 | 日本免费精品视频 | 人妻丝袜一区二区三区 | 一级免费视频 | 天天躁日日躁狠狠躁伊人 | 黄色片网站免费 | 精品亚洲一区二区三区 | 性一级视频 | 男生c女生 | 欧美日本一区二区 | 黄页视频在线免费观看 | free性欧美hd另类 | 丝袜老师办公室里做好紧好爽 | 欧美性高潮 | 日韩av一区二区三区在线观看 | 日韩视频国产 | 国产黄色电影 | 久久精品99久久久 | 欧洲美一区二区三区亚洲 | 久久潮| 国产精品调教视频 | 91中出| 精品久久香蕉国产线看观看亚洲 | 波多野结衣一区在线 | 亚洲第99页| 国产精品腿扒开做爽爽爽挤奶网站 | 91蜜桃婷婷狠狠久久综合9色 | 亚洲丁香 | 亚洲欧洲日韩综合 | av无码一区二区三区 | 在线观看免费日韩av | 1024手机看片日韩 | 97精品人妻一区二区三区 | 中文字幕+乱码+中文乱码www | www国产com |