linux中 probe函数的何时调用的?
點(diǎn)擊打開鏈接
linux中 probe函數(shù)何時(shí)調(diào)用的
???????? 所以的驅(qū)動教程上都說:只有設(shè)備和驅(qū)動的名字匹配,BUS就會調(diào)用驅(qū)動的probe函數(shù),但是有時(shí)我們要看看probe函數(shù)里面到底做了什么,還有傳遞給probe函數(shù)的參數(shù)我們就不知道在哪定義(反正不是我們在驅(qū)動里定義的),如果不知道傳遞進(jìn)的參數(shù),去看probe函數(shù)總是感覺不求甚解的樣子(你對系統(tǒng)不求甚解,系統(tǒng)也會對你的要求不求甚解的),心里對自己寫出的程序沒底,保不齊那天來個(gè)bug,就悲劇了。
???????? 這里以static int__devinit sst25l_probe(struct spi_device *spi)為例看看傳遞進(jìn)的參數(shù)structspi_device *spi到底是什么,在哪定義,什么時(shí)候定義,定義了有什么用…?(本著“five W and H”的原則打破沙鍋問到底)。首先struct spi_device *spi不是我們定義的驅(qū)動里定義的;其次在read,write等函數(shù)里都有struct spi_device *spi的影子,不過不是直接傳遞進(jìn)去的,而是通過傳遞進(jìn)去struct mtd_info *mtd,然后to_sst25l_flash(mtd),即container_of()出包含mtd的struct sst25l_flash *flash,其中flash里的第一個(gè)成員就是structspi_device *spi,而此成員的賦值就是將傳遞給probe中的struct spi_device *spi賦值給struct sst25l_flash *flash的,有代碼為證:
static int __devinit sst25l_probe(structspi_device *spi)
{
???????? structflash_info *flash_info;
???????? structsst25l_flash *flash;
???????? ……
???????? flash->spi = spi;//?將structspi_device *spi賦值給struct sst25l_flash *flash
???????? mutex_init(&flash->lock);
???????? dev_set_drvdata(&spi->dev,flash);// &spi->dev ->p->driver_data = flash保持flash
???????? ……
}
???????? 所以搞清楚structspi_device *spi的來源是搞清楚設(shè)備驅(qū)動與主控驅(qū)動的聯(lián)系紐帶的關(guān)鍵之一,當(dāng)然要首先搞清楚probe函數(shù)什么時(shí)候調(diào)用才能搞清楚struct spi_device *spi怎么傳遞的,其重要性不言而喻(雖然言了很多,^-^,有點(diǎn)唐僧了)。我們先從驅(qū)動的init開始入手,畢竟這是驅(qū)動注冊開始的地方,也是一系列后續(xù)操作引發(fā)的地方:
static int __init sst25l_init(void)
{
???????? returnspi_register_driver(&sst25l_driver);
}
???????? 里面只有一個(gè)函數(shù),最喜歡這樣的函數(shù)了:
int spi_register_driver(struct spi_driver*sdrv)
{
???????? sdrv->driver.bus= &spi_bus_type;
???????? if(sdrv->probe)
?????????????????? sdrv->driver.probe= spi_drv_probe;
???????? if(sdrv->remove)
?????????????????? sdrv->driver.remove= spi_drv_remove;
???????? if(sdrv->shutdown)
?????????????????? sdrv->driver.shutdown= spi_drv_shutdown;
?????????return driver_register(&sdrv->driver);
}
???????? 前面都是賦值,直接最后一個(gè)語句:
int driver_register(struct device_driver*drv)
{
???????? intret;
???????? structdevice_driver *other;
???????? ……
?????????ret = bus_add_driver(drv);
???????? if(ret)
?????????????????? returnret;
???????? ret= driver_add_groups(drv, drv->groups);
???????? if(ret)
?????????????????? bus_remove_driver(drv);
???????? returnret;
}
???????? bus_add_driver(drv)看著就像“好人”:
int bus_add_driver(struct device_driver*drv)
{
???????? structbus_type *bus;
???????? structdriver_private *priv;
???????? interror = 0;
???????? ……
???????? if(drv->bus->p->drivers_autoprobe) {
?????????????????? error=?driver_attach(drv);
?????????????????? if(error)
?????????????????? ???????? goto out_unregister;
???????? }
???????? ……
}
???????? driver_attach看著也很“友善”(函數(shù)名中帶get,init的一般都不是,如果里面有幾個(gè)“友善”的,一首歌中已經(jīng)告訴了我們解決的辦法:“xx就像偶爾撥不通的電話號碼,多試幾次總會回答,……”,如果網(wǎng)上找不到,只好挨個(gè)跟蹤了,我就這樣找的,笨人只好采取笨辦法,也是沒有辦法的辦法了):
int driver_attach(struct device_driver*drv)
{
???????? returnbus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
}
???????? 里面只有一個(gè)函數(shù),goon:
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;
????????
???????? if(!bus)
???????? ???????? return -EINVAL;
????????
???????? 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;
}
???????? 看到這里好像沒有我們想要找的attach,只執(zhí)行了個(gè)fn()函數(shù),腫么回事?到回頭看看哪里漏了,在bus_for_each_dev中傳遞了個(gè) __driver_attach,也就是在bus_for_each_dev執(zhí)行了__driver_attach(dev, data),那么它里面到底執(zhí)行了什么?
static int __driver_attach(struct device*dev, void *data)
{
???????? structdevice_driver *drv = data;
????????
?????????if (!driver_match_device(drv, dev))
???????? ?????????return 0;
????????
???????? if(dev->parent)/* Needed for USB */
?????????????????? device_lock(dev->parent);
???????? device_lock(dev);
???????? if(!dev->driver)
???????????????????driver_probe_device(drv, dev);
???????? device_unlock(dev);
???????? if(dev->parent)
?????????????????? device_unlock(dev->parent);
????????
???????? return0;
}
???????? 有個(gè)driver_probe_device(drv,dev),繼續(xù)跟蹤:
int driver_probe_device(structdevice_driver *drv, struct device *dev)
{
???????? intret = 0;
???????? ……
?????????ret = really_probe(dev, drv);
???????? pm_runtime_put_sync(dev);
?
???????? returnret;
}
???????? 有個(gè)really_probe(dev,drv),linux神馬的就喜歡這樣,經(jīng)常一個(gè)函數(shù)傳遞給另一函數(shù),后一個(gè)函數(shù)就是在前一個(gè)函數(shù)前加“do_”、“really_”、“__”,還經(jīng)常的就是宏定義的或inline的。
static int really_probe(struct device *dev,struct device_driver *drv)
{
???????? intret = 0;
???????? ……
???????? if(dev->bus->probe) {
???????????????????ret = dev->bus->probe(dev);
?????????????????? if(ret)
??????????????????????????? gotoprobe_failed;
???????? }else if (drv->probe) {
???????????????????ret = drv->probe(dev);
?????????????????? if(ret)
??????????????????????????? gotoprobe_failed;
???????? }
???????? ……
???????? returnret;
}
???????? 這里如果有總線上的probe函數(shù)就調(diào)用總線的probe函數(shù),如果沒有則調(diào)用drv的probe函數(shù)。
???????? 在static int__driver_attach(struct device *dev, void *data)中先調(diào)用了driver_match_device(drv,dev),用于匹配,成功才繼續(xù)執(zhí)行,否則直接返回了。driver_match_device(drv, dev)中:
static inline intdriver_match_device(struct device_driver *drv,
???????????????????????????????????? ????? struct device *dev)
{
???????? returndrv->bus->match ? drv->bus->match(dev, drv) : 1;
}
???????? 即如果match函數(shù)的指針不為空,則執(zhí)行此bus的match函數(shù),也就是為什么資料上老是說總線負(fù)責(zé)匹配設(shè)備和驅(qū)動了。這里也傳遞了參數(shù)struct device *dev,到底這個(gè)dev來自何方,會在下一篇文章中繼續(xù)跟蹤。
???????? 本文章參考:http://blog.chinaunix.net/space.php?uid=15887868&do=blog&id=2758294,對原作者表示感謝!
總結(jié)
以上是生活随笔為你收集整理的linux中 probe函数的何时调用的?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 打开CMDLINE中的 ” earlyp
- 下一篇: linux中probe函数中传递的参数来