仅卸载特定设备的内核模块(最好是从另一个内核模块中的代码中卸载)



我正在进行一个项目,其中我有一个管理系统,可以通过PCI Express将PCIe硬件设备导出到其他系统。我有一个工作的管理内核模块,但需要找到一种方法来确保我导出的设备在管理系统上没有为其加载驱动程序。否则,设备将以冲突告终,因为同一驱动程序将从2个不同的系统访问它&显然会引起问题。

例如,假设我在Manager上安装了一个双端口Intel 100MBps NIC设备,它将在系统中显示2个PCIe端点(例如Fn 0&1)。将为这两个设备加载Intel模块e1000。如果我想将该设备的端口2导出到另一个系统,我想将其从e1000模块"分离"。

有人知道在不破解内核或调整e1000驱动程序的探测功能的情况下实现这一点的干净方法吗?我不能简单地做rmmod,因为这将同时删除两个NIC设备的模块。我希望我没有导出的NIC在管理系统中保持功能,并且仍为其加载e1000驱动程序。

本质上,rmmod做到了这一点,但将删除所有探测到&由驾驶员所有。有没有办法告诉Linux"只为这个特定设备卸载模块"?在Windows上,我想这相当于在设备管理器中右键单击设备;选择"禁用"。

您可以通过编写以下方法禁用设备的驱动程序:

  • 使用sudo -i或在任何命令写入sudo之前以root用户身份操作。并遵循以下程序:
  • 转到/sys/bus/pci/<driver_name>/文件夹
  • 发出命令echo -n 0000:03:00.1 > unbind
  • 其中0000:03:00.1是您想要检测驱动程序的设备
  • 阅读此链接,了解有关pci总线的sysfs的信息

Linux驱动程序模型中负责设备/驱动程序配对的机制称为"总线"(通常通过/sys/bus中的条目控制)。问题是,您的设备所连接的特定总线驱动程序必须支持这种操作(在一般情况下,支持这种功能绝非易事)。

特别是对于PCI,如果您启用了"PCI热插拔",您将能够通过将数字写入/sys/bus/PCI中相应的"热插拔"条目来将设备从PCI总线上踢开(您也可以通过触发总线重新扫描来重新连接它们)。问题将在稍后开始,因为您必须以某种方式说服Linux设备子系统更喜欢您的驱动程序,而不是已经为相关设备id注册的驱动程序。

通常注册的驱动程序被添加到某种列表中,然后逐一试用,看看它们中的任何一个是否在"*_device_id"表中列出了新的或重新启用的设备。如果PCI子系统更喜欢按照"先注册,先尝试"的顺序尝试驱动程序,您将不得不破解它来实现您的目标。

要从设备解除PCI驱动程序的绑定,请使用sysfs中驱动程序的unbind文件。

来自Documentation/ABI/testing/sysfs-bus-pci:

/sys/bus/pci/drivers//解除绑定说明:将设备位置写入此文件将导致尝试从位于的设备解除绑定的驱动程序这个位置。当覆盖默认值时,这可能很有用绑定。位置的格式为:DDDD:BB:DD.F。即Domain:Bus:Device.Function,与在/sys/bus/pci/devices/中找到。例如:#echo 0000:00:19.0>/sys/bus/pci/drivers/foo/unbind

您可以通过重置相应设备的启用值来禁用特定的pci设备

例如:

echo 0 > /sys/bus/pci/devices/0000:00:1a.2/enable

最新更新