我有一个RTL8153基于 USB 以太网适配器,cdc_ether
默认使用该驱动程序。
我想使用该r8152
驱动程序,可以通过创建自定义 udev 规则来加载该驱动程序,如 Realtek 的 Linux 驱动程序源中所示。
但这里有一个令人困惑的部分,当我插入适配器时,cdc_ether
和r8152
模块都会被加载。我的问题是,
- 为什么?
- 如何找到负责加载的 udev 规则
cdc_ether
? - 我怎样才能停止加载该模块?因为在这种情况下不需要加载两个模块。
Udev规则的一行
ACTION=="add", DRIVER=="r8152", ATTR{idVendor}=="2357", ATTR{idProduct}=="0601", ATTR{bConfigurationValue}!="$env{REALTEK_NIC_MODE}", ATTR{bConfigurationValue}="$env{REALTEK_NIC_MODE}"
该DRIVER==
部分不是必需的。
答案1
ACTION=="add", DRIVER=="r8152", ATTR{idVendor}=="2357", ATTR{idProduct}=="0601", ATTR{bConfigurationValue}!="$env{REALTEK_NIC_MODE}", ATTR{bConfigurationValue}="$env{REALTEK_NIC_MODE}"
该 udev 规则的含义如下:“当将idVendor
值为 2357 和idProduct
值为 0601 的设备(由驱动程序“r8152”管理)添加到系统时,如果它bConfigurationValue
不是环境变量中定义的任何值REALTEK_NIC_MODE
,请将其设置bConfigurationValue
为那个值。”
换句话说,此 udev 规则不会加载 r8152 驱动程序,而是在必要时将设备切换到该驱动程序的正确模式。
当添加一个新设备时,Linux 内核基本上modprobe
使用设备的硬件 ID(以及其他一些东西)来运行,这些设备 ID 编码在它请求的模块的“名称”中。然后将该“名称”modprobe
与作为模块别名嵌入到每个模块中的通配符字符串进行比较。该depmod
命令收集这些别名并将其存储起来/lib/modules/<kernel version>/modules.alias[.bin]
以便快速搜索。您可以使用该命令查看嵌入到内核模块中的别名字符串modinfo
。
对于您的 USB 以太网适配器,“名称”类似于usb:v2357p0601d...
.不幸的是,该cdc_ether
模块有一个与之匹配的通配符别名。
中定义的任何别名/etc/modprobe.d
将优先于嵌入模块本身的别名。因此,您可以指定一个与您的以太网适配器匹配的别名,并导致r8152
加载模块。
尝试将其添加为/etc/modprobe.d/usbnic.conf
:
alias usb:v2357p0601d*dc*dsc*dp*ic*isc*ip*in* r8152
然后以 root 身份运行depmod -a
,拔下 USB 以太网适配器,卸载r8152
和cdc_ether
模块,重新插入以太网适配器,看看会发生什么。如果只加载r8152模块,那就好。
如果cdc_ether
仍然被加载,则别名可能需要更具体(即其中的一个或多个星号需要替换为实际值,无论它们是什么),以便使该别名最具体,从而“最佳”匹配。
更新:这是模块别名格式的描述:http://people.skolelinux.org/pere/blog/Modalias_strings___a_practical_way_to_map__stuff__to_hardware.html
答案2
最近的内核中有一个针对此问题的补丁:https://lkml.org/lkml/2017/9/25/711