0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Linux设备与驱动的手动解绑与手动绑定

Linux阅码场 来源:Linuxer 2020-08-03 16:25 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

众所周知,Linux靠设备与驱动之间的match,来完成设备与驱动的bind,从而触发驱动的probe()成员函数被执行。每个bus都有相应的match方法,完成match的总的入口函数是:

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

而这个总的入口函数又会调用到各自不同总线的match函数,对于platform bus而言,它的match函数就是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和驱动的name相同:

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

比如,设备的名字出现在驱动的ID表中:

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

比如device tree里面的compatible字段与驱动的dt兼容性字段匹配:

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

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

这种自动匹配非常简单,实施起来也非常容易。

但是有时候,这种自动匹配并不一定是我们想要的。比如我们有时候就是希望XXX设备用YYY驱动,而不是用XXX驱动。工程中有手动匹配的需求,最典型的场景是VFIO的场景,想让设备与内核空间原本绑定的驱动解绑,转而采用内核空间的通用VFIO驱动,而VFIO驱动又提供了userspace驾驭设备的能力。

下面我们来从原理和实践上演示这种手动的unbind和bind是怎么进行的。在《Linux设备驱动开发详解》一书中,我们给出了一个简单的globalfifo设备和globalfifo驱动:

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”,符合此行的匹配规则:

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

设备和驱动匹配成功,从sysfs也可以看出:

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

现在我们来写一个第三者driver,名字叫做globalxxx,然后我们想把globalfifo device的driver指向globalxxx。因此我们要完成2步:

unbind:解除globalfifo driver与globalfifo device的绑定

bind: 进行globalxxxdriver与globalfifo device的绑定

第三者globalxxx驱动代码类似:

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(每次设备和驱动bind成功,驱动probe都会执行),remove(每次设备和驱动unbind成功,驱动remove都会执行),最后处于unbind状态。

现在我们来把globalfifo设备bind到globalxxx驱动:

绑定的时候提示错误!

绑定的时候提示错误!!

绑定的时候提示错误!!!

前面我们用globalfifo的driver去bind globalfifo的device的时候,是想怎么绑就怎么绑的,想绑多少次就绑多少次的!为什么换了globalxxx来绑就不行了呢?

爱情不是你想卖想买就能卖

让我挣开 让我明白

放手你的爱

我们来看看这个bind sysfs入口工作的函数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()成立,否则内核会返回-ENODEV错误:

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

根据前文对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:

现在globalfifo device可以在globalxxx和globalfifo这2个driver里面进行自由地bind和unbind!

看到这里,客官们一定觉得这太特么狗血了!不是说可以自由地绑定第三者吗?为嘛还要求这个第三者驱动与这个原先的设备匹配呢?这有嘛意思呢?

别忘了,在platform_match中还有这么一行:

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

设备完全可以自由地宣布她喜欢的第三者driver,哪怕这个第三者driver和她本身完全没有任何的匹配因子,操作的入口就是driver_override sysfs文件。

我们完全可以保留globalxxx驱动的原样

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八竿子打不着,也是可以驱动globalfifo device的。工程里面如果我们想用VFIO的方式来驱动一个设备,就可以这样做:

echo vfio-platform > driver_override

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 驱动
    +关注

    关注

    12

    文章

    2001

    浏览量

    88793
  • Linux
    +关注

    关注

    88

    文章

    11854

    浏览量

    219824
  • 函数
    +关注

    关注

    3

    文章

    4423

    浏览量

    68036

原文标题:宋宝华:Linux设备与驱动的手动解绑与手动绑定

文章出处:【微信号:LinuxDev,微信公众号:Linux阅码场】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    手动控制输出模块:特性与规格详解

    手动控制输出模块:特性与规格详解 在电子工程领域,手动控制输出模块是一种重要的设备,它在众多电子系统中发挥着关键作用。今天,我们就来详细了解一下Grayhill公司的手动控制输出模块。
    的头像 发表于 05-16 12:05 278次阅读

    变频器的手动旁路方式与自动旁路方式区别

    变频器的手动旁路与自动旁路,核心区别在于切换操作的执行者是 人 还是 系统 。这决定了它们在设备成本、操作方式和适用场景上有很大不同。 我把两者的核心区别整理成了下面的表格,方便你对比: 对比维度
    的头像 发表于 04-19 17:16 135次阅读
    变频器的<b class='flag-5'>手动</b>旁路方式与自动旁路方式区别

    NXP数字钥匙 3.0-真正实现免手动汽车门禁

    NXP数字钥匙3.0-真正实现免手动汽车门禁
    发表于 04-14 14:11 1次下载

    是否可以将 UART4 与 Linux tty 设备绑定,并将其用于 EVK 板与主机 PC 以及 UART2 之间的通信?

    on the Cortex-M7 core on the EVK board according to the hardware user\'s guide. 是否可以将 UART4 与 Linux tty 设备绑定,并将
    发表于 04-10 11:47

    Linux内核驱动开发的技术核心精要

    (DT)已成为ARM平台标准硬件描述,将板级细节从内核代码中耦。开发者需熟悉设备树语法、属性解析(of_函数)以及绑定文档编写。驱动中应获取资源(地址、中断、时钟)而不硬编码。
    发表于 03-10 13:56

    变频器手动旁路与自动旁路的优缺点比较

    变频器作为现代工业控制中不可或缺的设备,其旁路功能的设计直接影响系统的可靠性和灵活性。手动旁路与自动旁路是两种常见的配置方案,它们在应用场景、成本控制、安全性能等方面存在显著差异,需要根据实际需求进行选择。以下从工作原理、技术特点、适用场景等维度展开详细对比分析。
    的头像 发表于 02-27 17:03 485次阅读
    变频器<b class='flag-5'>手动</b>旁路与自动旁路的优缺点比较

    从RK3576 Linux SDK手动适配RK3568,省下时间又省钱

    基于 RK3568 开发物联网设备,但官方 SDK 申请还在排队,于是决定从已有的 RK3576 Linux SDK 手动适配,最终成功编译出 RK3568 的镜像。今天就来拆解这个适配过程,告诉你 “为什么要这么操作”,以及背
    的头像 发表于 02-02 17:17 1783次阅读
    从RK3576 <b class='flag-5'>Linux</b> SDK<b class='flag-5'>手动</b>适配RK3568,省下时间又省钱

    全自动vs手动:哪种芯片烧录机更适合你的工厂产线?

    本文系统对比了全自动与手动芯片烧录机的核心差异。全自动设备适用于大批量、单一型号的稳定生产,以高投入换取超高产能、极致良率与完整追溯能力。手动设备则凭借极低的切换成本与投入,完美适配小
    的头像 发表于 01-09 10:39 2078次阅读
    全自动vs<b class='flag-5'>手动</b>:哪种芯片烧录机更适合你的工厂产线?

    【免费送书】成为硬核Linux开发者:《Linux 设备驱动开发(第 2 版)》

    Linux系统的设备驱动开发,一直给人门槛较高的印象,主要因内核机制抽象、需深度理解硬件原理、开发调试难度大所致。2021年,一本讲解驱动开发的专著问世即获市场青睐,畅销近万册——这便
    的头像 发表于 11-18 08:06 1953次阅读
    【免费送书】成为硬核<b class='flag-5'>Linux</b>开发者:《<b class='flag-5'>Linux</b> <b class='flag-5'>设备</b><b class='flag-5'>驱动</b>开发(第 2 版)》

    原理图手动连线太繁琐,自动连线来救场!

    原理图绘图中有比较多且繁琐的操作,还极其容易出错。比如:1.逐条网络命名:在原理图中为大量重要的电源、时钟、差分对网络手动添加有意义的名称(如DDR_DQ[0],PCIe_CLK100M_P),极其
    的头像 发表于 11-10 18:30 876次阅读
    原理图<b class='flag-5'>手动</b>连线太繁琐,自动连线来救场!

    如何判断电能质量在线监测装置时钟模块需要进行手动校准?

    判断电能质量在线监测装置时钟模块是否需要手动校准,核心是识别 “ 自动同步失效 ” 或 “ 时钟偏差超出对应精度等级允许范围 ” 两类场景,结合装置状态提示、数据对比、功能异常等直观信号,按 “先查
    的头像 发表于 10-15 17:52 1059次阅读

    无人机自动巡检系统:从手动操作到智能化的技术变革

           无人机自动巡检系统:从手动操作到智能化的技术变革        在无人机技术发展过程中,其操控方式经历了从完全依赖飞手手动操作到逐步实现自动化、智能化巡检的重大飞跃。早期手动飞行模式
    的头像 发表于 09-11 13:16 928次阅读

    阿图什小台式测径仪的自动模式与手动模式分别是什么?

    ”指示设备对电机转速的控制方式,分为“手动模式M”和“自动模式A”。 模式切换方法 在主界面下按“模式”按键,设备在自动和手动模式间切换。 “自动模式A”下,
    发表于 07-29 15:01

    API让电商“飞”起来,告别手动操作

    ​ 在当今快节奏的电商环境中,手动处理订单、更新库存或管理客户数据不仅耗时耗力,还容易出错。许多商家因此陷入效率瓶颈,影响业务增长。幸运的是,API(应用程序编程接口)技术为电商自动化提供了强大支持
    的头像 发表于 07-16 10:31 604次阅读
    API让电商“飞”起来,告别<b class='flag-5'>手动</b>操作

    季丰电子推出低高温手动探针台设备

    为满足客户对低温测试的要求,季丰电子成功自研了低高温手动探针台,目前已在季丰张江FA投入使用,该机台填补了传统常规型手动探针台无法实现低温测试环境的空白。
    的头像 发表于 06-05 13:38 1138次阅读