99精品伊人亚洲|最近国产中文炮友|九草在线视频支援|AV网站大全最新|美女黄片免费观看|国产精品资源视频|精彩无码视频一区|91大神在线后入|伊人终合在线播放|久草综合久久中文

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

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

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

Linux設備與驅(qū)動的手動解綁與手動綁定

Linux閱碼場 ? 來源:Linuxer ? 2020-08-03 16:25 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

眾所周知,Linux靠設備與驅(qū)動之間的match,來完成設備與驅(qū)動的bind,從而觸發(fā)驅(qū)動的probe()成員函數(shù)被執(zhí)行。每個bus都有相應的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;}

而這個總的入口函數(shù)又會調(diào)用到各自不同總線的match函數(shù),對于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有很多方法成立,比如設備的name和驅(qū)動的name相同:

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

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

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

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

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

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

這種自動匹配非常簡單,實施起來也非常容易。

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

下面我們來從原理和實踐上演示這種手動的unbind和bind是怎么進行的。在《Linux設備驅(qū)動開發(fā)詳解》一書中,我們給出了一個簡單的globalfifo設備和globalfifo驅(qū)動:

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

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

globalfifo的device和driver各自找到了對方。

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

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

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

第三者globalxxx驅(qū)動代碼類似:

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);

下面我們來完成第一步的unbind,這一步很簡單,跑到/sys/bus/platform/drivers/globalfifo目錄,把設備globalfifo的名字寫進去unbind文件:

當然我們也可以來回折騰著unbind,bind著玩:

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

現(xiàn)在我們來把globalfifo設備bind到globalxxx驅(qū)動:

綁定的時候提示錯誤!

綁定的時候提示錯誤!!

綁定的時候提示錯誤!??!

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

愛情不是你想賣想買就能賣

讓我掙開 讓我明白

放手你的愛

我們來看看這個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; } } ...}

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

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

根據(jù)前文對platform_match()的代碼分析,globalxxx driver和globalfifo device確實八竿子都打不著!!沒有任何匹配因子。

下面我們來把globalxxx的代碼稍微改一下,通過ID表來增加一個匹配因子:

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個driver里面進行自由地bind和unbind!

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

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

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

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

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

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

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

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

echo vfio-platform > driver_override

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

    關注

    12

    文章

    1916

    瀏覽量

    86904
  • Linux
    +關注

    關注

    87

    文章

    11509

    瀏覽量

    213711
  • 函數(shù)
    +關注

    關注

    3

    文章

    4379

    瀏覽量

    64830

原文標題:宋寶華:Linux設備與驅(qū)動的手動解綁與手動綁定

文章出處:【微信號:LinuxDev,微信公眾號:Linux閱碼場】歡迎添加關注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關推薦
    熱點推薦

    季豐電子推出低高溫手動探針臺設備

    為滿足客戶對低溫測試的要求,季豐電子成功自研了低高溫手動探針臺,目前已在季豐張江FA投入使用,該機臺填補了傳統(tǒng)常規(guī)型手動探針臺無法實現(xiàn)低溫測試環(huán)境的空白。
    的頭像 發(fā)表于 06-05 13:38 ?334次閱讀

    Princetel 推出新的手動電纜卷筒在線配置器

    新的數(shù)字工具使工程師能夠配置和下載手動電纜卷筒的 3D CAD 模型 Princetel 成立于 2000 年,是一家垂直一體化公司,專門設計和制造光纖旋轉(zhuǎn)接頭 (FORJ)、按訂單生產(chǎn)的電氣滑環(huán)
    發(fā)表于 04-18 15:41

    手動檢測的終結(jié)者:機器人氣密性測試設備來襲

    在制造業(yè)的精密檢測領域,氣密性測試一直是保證產(chǎn)品質(zhì)量的關鍵環(huán)節(jié)。然而,傳統(tǒng)的手動檢測方法存在效率低下、誤差較大等問題,已經(jīng)無法滿足現(xiàn)代工業(yè)對高質(zhì)量和高效率的追求。隨著科技的進步,機器人氣密性測試設備
    的頭像 發(fā)表于 04-16 14:50 ?251次閱讀
    <b class='flag-5'>手動</b>檢測的終結(jié)者:機器人氣密性測試<b class='flag-5'>設備</b>來襲

    告別手動時代:揭秘蔡司探針清潔的智能革命

    您是否正面臨以下測量挑戰(zhàn)? 手動清潔三坐標探針耗時耗力,影響生產(chǎn)進度? 微小探針清潔困難,容易造成損壞,損失慘重? 探針因積塵或靜電干擾測量結(jié)果,缺乏有效解決方案? 蔡司探針自動清潔裝置將是您的理想
    發(fā)表于 03-05 14:59 ?240次閱讀
    告別<b class='flag-5'>手動</b>時代:揭秘蔡司探針清潔的智能革命

    RobotStudio 6.08的手動操作方法

    本文給大家介紹一下 RobotStudio 6.08的手動操作方法 RobotStudio 6.08手動操作? RobotStudio 6.08是學習和調(diào)試ABB機器人必須掌握的使用軟件。 在開始
    的頭像 發(fā)表于 12-18 09:53 ?4402次閱讀
    RobotStudio 6.08的<b class='flag-5'>手動</b>操作方法

    RS PRO手動工具產(chǎn)品系列概述

    無論是機械維修、裝配生產(chǎn)線還是日常的設備維護,手動工具都扮演著重要的角色,為工業(yè)生產(chǎn)的順利進行提供保障。
    的頭像 發(fā)表于 12-05 15:55 ?666次閱讀

    ADS8332在手動觸發(fā)、手動通道選擇情況下,它的SDI是如何進行指令的?

    芯片在手動觸發(fā)、手動通道選擇情況下,它的SDI是如何進行指令的,因為比如選擇通道0需要指令b0000;但是讀數(shù)則需要指令1101。 同時能否解讀一下內(nèi)部時鐘CCLK和外部時鐘SCLK之間的關系,后續(xù)可能會用到自動觸發(fā)。
    發(fā)表于 11-21 07:55

    告別手動打壓,這款壓力源更高效!

    隨著工業(yè)自動化的快速發(fā)展,一種更加高效、精準的解決方案應用而生,它有效的解決了氣體壓縮比大、手動打壓效率低、打壓困難等問題——電動壓力源!
    的頭像 發(fā)表于 09-25 10:28 ?576次閱讀
    告別<b class='flag-5'>手動</b>打壓,這款壓力源更高效!

    使用電壓監(jiān)控器上的手動復位來斷開按鈕開關

    電子發(fā)燒友網(wǎng)站提供《使用電壓監(jiān)控器上的手動復位來斷開按鈕開關.pdf》資料免費下載
    發(fā)表于 09-18 10:44 ?0次下載
    使用電壓監(jiān)控器上的<b class='flag-5'>手動</b>復位來斷開按鈕開關

    linux系統(tǒng)的設備驅(qū)動一般分幾類

    Linux系統(tǒng)的設備驅(qū)動是操作系統(tǒng)與硬件設備之間的橋梁,負責實現(xiàn)操作系統(tǒng)與硬件設備之間的通信和控制。Li
    的頭像 發(fā)表于 08-30 15:13 ?1009次閱讀

    Linux設備驅(qū)動程序分類有哪些

    Linux設備驅(qū)動程序是操作系統(tǒng)與硬件設備之間的橋梁,負責實現(xiàn)硬件設備與操作系統(tǒng)之間的通信和控制。Lin
    的頭像 發(fā)表于 08-30 15:11 ?1232次閱讀

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

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

    延時開關改手動開關怎么接線

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

    萬能式斷路器怎么手動合閘

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

    TE Connectivity高級手動工具解決方案

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