0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Linux設(shè)備與驅(qū)動(dòng)的手動(dòng)解綁與手動(dòng)綁定

Linux閱碼場(chǎng) ? 來(lái)源:Linuxer ? 2020-08-03 16:25 ? 次閱讀

眾所周知,Linux靠設(shè)備與驅(qū)動(dòng)之間的match,來(lái)完成設(shè)備與驅(qū)動(dòng)的bind,從而觸發(fā)驅(qū)動(dòng)的probe()成員函數(shù)被執(zhí)行。每個(gè)bus都有相應(yīng)的match方法,完成match的總的入口函數(shù)是:

static inline int driver_match_device(struct device_driver *drv, struct device *dev){ return drv->bus->match ? drv->bus->match(dev, drv) : 1;}

而這個(gè)總的入口函數(shù)又會(huì)調(diào)用到各自不同總線的match函數(shù),對(duì)于platform bus而言,它的match函數(shù)就是platform_match()

static int platform_match(struct device *dev, struct device_driver *drv){ struct platform_device *pdev = to_platform_device(dev); struct platform_driver *pdrv = to_platform_driver(drv); /* When driver_override is set, only bind to the matching driver */ if (pdev->driver_override) return !strcmp(pdev->driver_override, drv->name); /* Attempt an OF style match first */ if (of_driver_match_device(dev, drv)) return 1; /* Then try ACPI style match */ if (acpi_driver_match_device(dev, drv)) return 1; /* Then try to match against the id table */ if (pdrv->id_table) return platform_match_id(pdrv->id_table, pdev) != NULL; /* fall-back to driver name match */ return (strcmp(pdev->name, drv->name) == 0);}

從代碼可以看出,platform的driver和device之間的match有很多方法成立,比如設(shè)備的name和驅(qū)動(dòng)的name相同:

strcmp(pdev->name, drv->name) == 0

比如,設(shè)備的名字出現(xiàn)在驅(qū)動(dòng)的ID表中:

if (pdrv->id_table) return platform_match_id(pdrv->id_table, pdev) != NULL;

比如device tree里面的compatible字段與驅(qū)動(dòng)的dt兼容性字段匹配:

if (of_driver_match_device(dev, drv)) return 1;

只要符合其中任意一種,driver和device都可以匹配上。

這種自動(dòng)匹配非常簡(jiǎn)單,實(shí)施起來(lái)也非常容易。

但是有時(shí)候,這種自動(dòng)匹配并不一定是我們想要的。比如我們有時(shí)候就是希望XXX設(shè)備用YYY驅(qū)動(dòng),而不是用XXX驅(qū)動(dòng)。工程中有手動(dòng)匹配的需求,最典型的場(chǎng)景是VFIO的場(chǎng)景,想讓設(shè)備與內(nèi)核空間原本綁定的驅(qū)動(dòng)解綁,轉(zhuǎn)而采用內(nèi)核空間的通用VFIO驅(qū)動(dòng),而VFIO驅(qū)動(dòng)又提供了userspace駕馭設(shè)備的能力。

下面我們來(lái)從原理和實(shí)踐上演示這種手動(dòng)的unbind和bind是怎么進(jìn)行的。在《Linux設(shè)備驅(qū)動(dòng)開(kāi)發(fā)詳解》一書(shū)中,我們給出了一個(gè)簡(jiǎn)單的globalfifo設(shè)備和globalfifo驅(qū)動(dòng):

globalfifo-dev.ko(增加platform_device的模塊):

static int __init globalfifodev_init(void){ int ret; globalfifo_pdev=platform_device_alloc("globalfifo",-1); ret = platform_device_add(globalfifo_pdev);... return 0; }module_init(globalfifodev_init);

globalfifo.ko(增加platform_driver的模塊):

static struct platform_driver globalfifo_driver = { .driver = { .name = "globalfifo", .owner = THIS_MODULE, }, .probe = globalfifo_probe, .remove = globalfifo_remove,}; module_platform_driver(globalfifo_driver);

由于其中的platform_driver和platform_device的name都是“globalfifo”,符合此行的匹配規(guī)則:

strcmp(pdev->name, drv->name) == 0

設(shè)備和驅(qū)動(dòng)匹配成功,從sysfs也可以看出:

globalfifo的device和driver各自找到了對(duì)方。

現(xiàn)在我們來(lái)寫(xiě)一個(gè)第三者driver,名字叫做globalxxx,然后我們想把globalfifo device的driver指向globalxxx。因此我們要完成2步:

unbind:解除globalfifo driver與globalfifo device的綁定

bind: 進(jìn)行g(shù)lobalxxxdriver與globalfifo device的綁定

第三者globalxxx驅(qū)動(dòng)代碼類(lèi)似:

globalxxx.ko(增加platform_driver的模塊):

static struct platform_driver globalxxx_driver = { .driver = { .name = "globalxxx", .owner = THIS_MODULE, }, .probe = globalxxx_probe, .remove = globalxxx_remove,}; module_platform_driver(globalxxx_driver);

下面我們來(lái)完成第一步的unbind,這一步很簡(jiǎn)單,跑到/sys/bus/platform/drivers/globalfifo目錄,把設(shè)備globalfifo的名字寫(xiě)進(jìn)去unbind文件:

當(dāng)然我們也可以來(lái)回折騰著unbind,bind著玩:

這樣我們看到一堆的probe(每次設(shè)備和驅(qū)動(dòng)bind成功,驅(qū)動(dòng)probe都會(huì)執(zhí)行),remove(每次設(shè)備和驅(qū)動(dòng)unbind成功,驅(qū)動(dòng)remove都會(huì)執(zhí)行),最后處于unbind狀態(tài)。

現(xiàn)在我們來(lái)把globalfifo設(shè)備bind到globalxxx驅(qū)動(dòng):

綁定的時(shí)候提示錯(cuò)誤!

綁定的時(shí)候提示錯(cuò)誤!!

綁定的時(shí)候提示錯(cuò)誤!?。?/p>

前面我們用globalfifo的driver去bind globalfifo的device的時(shí)候,是想怎么綁就怎么綁的,想綁多少次就綁多少次的!為什么換了globalxxx來(lái)綁就不行了呢?

愛(ài)情不是你想賣(mài)想買(mǎi)就能賣(mài)

讓我掙開(kāi) 讓我明白

放手你的愛(ài)

我們來(lái)看看這個(gè)bind sysfs入口工作的函數(shù)bind_store():

static ssize_t bind_store(struct device_driver *drv, const char *buf, size_t count){ ... dev = bus_find_device_by_name(bus, NULL, buf); if (dev && dev->driver == NULL && driver_match_device(drv, dev)) { err = device_driver_attach(drv, dev); if (err > 0) { /* success */ err = count; } else if (err == 0) { /* driver didn't accept device */ err = -ENODEV; } } ...}

看起來(lái),如果要強(qiáng)行bind,仍然需要device_driver_attach()成立,否則內(nèi)核會(huì)返回-ENODEV錯(cuò)誤:

} else if (err == 0) { /* driver didn't accept device */ err = -ENODEV; }

根據(jù)前文對(duì)platform_match()的代碼分析,globalxxx driver和globalfifo device確實(shí)八竿子都打不著?。](méi)有任何匹配因子。

下面我們來(lái)把globalxxx的代碼稍微改一下,通過(guò)ID表來(lái)增加一個(gè)匹配因子:

static const struct platform_device_id globalxxx_ids[] = { { .name = "globalfifo", }, {}};MODULE_DEVICE_TABLE(platform, globalxxx_ids); static struct platform_driver globalxxx_driver = { .driver = { .name = "globalxxx", .owner = THIS_MODULE, }, .id_table = globalxxx_ids, .probe = globalxxx_probe, .remove = globalxxx_remove,}; module_platform_driver(globalxxx_driver);

rmmod和insmod globalxxx.ko

然后重新bind:

現(xiàn)在globalfifo device可以在globalxxx和globalfifo這2個(gè)driver里面進(jìn)行自由地bind和unbind!

看到這里,客官們一定覺(jué)得這太特么狗血了!不是說(shuō)可以自由地綁定第三者嗎?為嘛還要求這個(gè)第三者驅(qū)動(dòng)與這個(gè)原先的設(shè)備匹配呢?這有嘛意思呢?

別忘了,在platform_match中還有這么一行:

if (pdev->driver_override) return !strcmp(pdev->driver_override, drv->name);

設(shè)備完全可以自由地宣布她喜歡的第三者driver,哪怕這個(gè)第三者driver和她本身完全沒(méi)有任何的匹配因子,操作的入口就是driver_override sysfs文件。

我們完全可以保留globalxxx驅(qū)動(dòng)的原樣

static struct platform_driver globalxxx_driver = { .driver = { .name = "globalxxx", .owner = THIS_MODULE, }, .probe = globalxxx_probe, .remove = globalxxx_remove,};

不去增加任何的id_table,而換做到globalfifo device里面去寫(xiě)driver_override文件,宣布globalxxx driver可以匹配globalfifo device。

這樣之后,哪怕globalxxx driver和globalfifo device八竿子打不著,也是可以驅(qū)動(dòng)globalfifo device的。工程里面如果我們想用VFIO的方式來(lái)驅(qū)動(dòng)一個(gè)設(shè)備,就可以這樣做:

echo vfio-platform > driver_override

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 驅(qū)動(dòng)
    +關(guān)注

    關(guān)注

    12

    文章

    1812

    瀏覽量

    85045
  • Linux
    +關(guān)注

    關(guān)注

    87

    文章

    11161

    瀏覽量

    208460
  • 函數(shù)
    +關(guān)注

    關(guān)注

    3

    文章

    4256

    瀏覽量

    62223

原文標(biāo)題:宋寶華:Linux設(shè)備與驅(qū)動(dòng)的手動(dòng)解綁與手動(dòng)綁定

文章出處:【微信號(hào):LinuxDev,微信公眾號(hào):Linux閱碼場(chǎng)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    linux驅(qū)動(dòng)程序的編譯方法有哪兩種

    Linux驅(qū)動(dòng)程序的編譯方法主要可以歸納為兩種: 手動(dòng)編譯 和 使用內(nèi)核構(gòu)建系統(tǒng)(Makefile)自動(dòng)編譯 。 1. 手動(dòng)編譯 手動(dòng)編譯
    的頭像 發(fā)表于 08-30 14:39 ?372次閱讀

    延時(shí)開(kāi)關(guān)改手動(dòng)開(kāi)關(guān)怎么接線

    :延時(shí)開(kāi)關(guān)是一種具有延時(shí)功能的開(kāi)關(guān),當(dāng)按下開(kāi)關(guān)按鈕時(shí),電路會(huì)在設(shè)定的延時(shí)時(shí)間后自動(dòng)斷開(kāi)或閉合。延時(shí)開(kāi)關(guān)通常用于控制照明、通風(fēng)、加熱等設(shè)備,以實(shí)現(xiàn)節(jié)能和安全的目的。 手動(dòng)開(kāi)關(guān):手動(dòng)開(kāi)關(guān)是一種簡(jiǎn)單的開(kāi)關(guān),按下開(kāi)關(guān)按
    的頭像 發(fā)表于 08-19 15:49 ?329次閱讀

    萬(wàn)能式斷路器怎么手動(dòng)合閘

    萬(wàn)能式斷路器是一種廣泛應(yīng)用于電力系統(tǒng)中的保護(hù)和控制設(shè)備。它具有多種功能,包括過(guò)載保護(hù)、短路保護(hù)和遠(yuǎn)程控制等。手動(dòng)合閘是斷路器操作的一種方式,通常在自動(dòng)控制失效或需要手動(dòng)干預(yù)的情況下使用。 1.
    的頭像 發(fā)表于 08-14 15:52 ?1173次閱讀

    TE Connectivity高級(jí)手動(dòng)工具解決方案

    CERTI-CRIMP手動(dòng)工具是業(yè)界頂級(jí)的優(yōu)質(zhì)手動(dòng)操作工具,用于壓接各種端子、接觸件和專(zhuān)用布線器件。這些工具根據(jù)實(shí)現(xiàn)始終如一的高品質(zhì)端接所需的具體規(guī)范設(shè)計(jì)而成。使用壽命有可能達(dá)到 50,000 次以上,具體取決于操作員的維護(hù)。
    的頭像 發(fā)表于 07-19 16:23 ?207次閱讀
    TE Connectivity高級(jí)<b class='flag-5'>手動(dòng)</b>工具解決方案

    abb工業(yè)機(jī)器人手動(dòng)操作有哪三種模式?

    ABB工業(yè)機(jī)器人是一種廣泛應(yīng)用于制造業(yè)、物流、醫(yī)療等領(lǐng)域的自動(dòng)化設(shè)備。它具有高度的靈活性和精確性,可以完成各種復(fù)雜的任務(wù)。在操作ABB工業(yè)機(jī)器人時(shí),通常有三種手動(dòng)操作模式:手動(dòng)單軸移動(dòng)模式、
    的頭像 發(fā)表于 06-16 16:44 ?3411次閱讀

    如何手動(dòng)往esp32 arp列表中添加自定義的arp綁定信息?

    我目前需要手動(dòng)往esp32 arp列表中添加自定義的arp綁定信息,而非arp請(qǐng)求獲得,因?yàn)榱硪环?b class='flag-5'>設(shè)備無(wú)法完成arp應(yīng)答 如IP為:192.168.88.2 MAC為:00:0A:35:01:FE:C0 arp
    發(fā)表于 06-07 08:14

    淺析非集中控制型消防應(yīng)急照明和疏散指示系統(tǒng)手動(dòng)控制的設(shè)計(jì)與應(yīng)用

    淺析非集中控制型消防應(yīng)急照明和疏散指示系統(tǒng)手動(dòng)控制的設(shè)計(jì)與應(yīng)用 張穎姣 摘要:針對(duì)非集中控制型消防應(yīng)急照明和疏散指示系統(tǒng)在火災(zāi)確認(rèn)后如何手動(dòng)控制系統(tǒng)的應(yīng)急啟動(dòng)存在的實(shí)際問(wèn)題:在哪里手動(dòng)控制?由誰(shuí)來(lái)
    的頭像 發(fā)表于 04-15 17:06 ?941次閱讀
    淺析非集中控制型消防應(yīng)急照明和疏散指示系統(tǒng)<b class='flag-5'>手動(dòng)</b>控制的設(shè)計(jì)與應(yīng)用

    手動(dòng)光纖檢偏器產(chǎn)品介紹

    手動(dòng)光纖檢偏器用于光纖及光器件的偏振特性測(cè)試,配合光功率計(jì)或光電探測(cè)器可實(shí)現(xiàn)輸入光偏振消光比的精確測(cè)量。手動(dòng)光纖檢偏器模塊內(nèi)部采用平凸透鏡與高性能偏振片,僅需將光纖連接器旋入標(biāo)準(zhǔn) FC 型適配器
    發(fā)表于 01-23 09:20 ?0次下載

    手動(dòng)光纖起偏器產(chǎn)品介紹

    手動(dòng)光纖起偏器是基于康寧Polarcor? 全玻璃偏振片與六自由度光纖/空間光耦合裝置構(gòu)成的精密手動(dòng)調(diào)節(jié)光纖型起偏器,專(zhuān)門(mén)用于保偏光纖、無(wú)源偏振器件的性能測(cè)試。光路設(shè)計(jì)采用外置一體化空間光路,六
    發(fā)表于 01-23 09:19 ?0次下載

    innovus中如何手動(dòng)拉線及常用快捷鍵

    route之后已經(jīng)用了相當(dāng)多的辦法(包括調(diào)整floorplan)之后,仍然有drc或者antenna,且violation數(shù)量不多時(shí),就需要手動(dòng)拉線了。本文介紹了innouvs里手動(dòng)拉線常用的工具和快捷鍵。
    的頭像 發(fā)表于 01-08 10:05 ?3596次閱讀
    innovus中如何<b class='flag-5'>手動(dòng)</b>拉線及常用快捷鍵

    手動(dòng)和時(shí)空開(kāi)關(guān)控制電路原理圖

    這是通過(guò)一個(gè)轉(zhuǎn)換開(kāi)關(guān)切換手動(dòng)與時(shí)控開(kāi)關(guān)控制電機(jī)的電路。
    的頭像 發(fā)表于 12-14 13:30 ?1284次閱讀
    <b class='flag-5'>手動(dòng)</b>和時(shí)空開(kāi)關(guān)控制電路原理圖

    linux手動(dòng)設(shè)置網(wǎng)絡(luò)參數(shù)

    Linux 是一種廣泛使用的操作系統(tǒng),提供了豐富的網(wǎng)絡(luò)配置選項(xiàng),允許用戶(hù)手動(dòng)設(shè)置網(wǎng)絡(luò)參數(shù),以滿(mǎn)足各種網(wǎng)絡(luò)需求。本文將詳盡、詳實(shí)、細(xì)致地介紹 Linux手動(dòng)設(shè)置網(wǎng)絡(luò)參數(shù)的方法,包括
    的頭像 發(fā)表于 11-27 15:20 ?628次閱讀

    Linux內(nèi)核驅(qū)動(dòng)與單個(gè)PCI設(shè)備綁定和解綁定

    Linux內(nèi)核2.6.13-rc3以前,驅(qū)動(dòng)設(shè)備之間的綁定和解只能通過(guò)insmod(modprobe)和rmmod來(lái)實(shí)現(xiàn),但是這種實(shí)現(xiàn)
    的頭像 發(fā)表于 11-17 17:11 ?1435次閱讀
    <b class='flag-5'>Linux</b>內(nèi)核<b class='flag-5'>驅(qū)動(dòng)</b>與單個(gè)PCI<b class='flag-5'>設(shè)備</b>的<b class='flag-5'>綁定</b>和解<b class='flag-5'>綁定</b>

    TE Connectivity高級(jí)手動(dòng)工具解決方案(下)

    CERTI-CRIMP手動(dòng)工具是業(yè)界頂級(jí)的優(yōu)質(zhì)手動(dòng)操作工具,用于壓接各種端子、接觸件和專(zhuān)用布線器件。這些工具根據(jù)實(shí)現(xiàn)始終如一的高品質(zhì)端接所需的具體規(guī)范設(shè)計(jì)而成。使用壽命有可能達(dá)到 50,000 次以上,具體取決于操作員的維護(hù)。
    的頭像 發(fā)表于 10-27 12:21 ?427次閱讀
    TE Connectivity高級(jí)<b class='flag-5'>手動(dòng)</b>工具解決方案(下)

    JLink手動(dòng)添加Artery MCU

    JLink 如何手動(dòng)添加 Artery MCU
    發(fā)表于 10-23 07:36