Linux 总线模型与 bind/unbind 完整解析

Linux 总线模型与 bind/unbind 完整解析

1. 为什么 /sys/bus/ 不是"全部总线"

在 Linux 设备模型中,每种总线类型(platform、PCI、I²C、SPI、USB 等)都会在 /sys/bus/ 下注册一个目录。你看到的目录取决于:

  • 内核配置 :如果内核没启用某个总线(比如 CAN 总线),就不会有 /sys/bus/can/。
  • 驱动是否启用 :如果驱动没注册成功,对应的 drivers/ 子目录也不会出现。

因此 /sys/bus/ 是动态的,不是固定全集。


2. bind/unbind 的原理

在 /sys/bus/<bus>/drivers/<driver>/ 下,可能会有 bind 和 unbind 文件:

  • 生成条件 :
    • 驱动通过标准 API 注册(如 platform_driver_register()、i2c_add_driver()、pci_register_driver())。
    • 驱动实现了 probe() 和 remove()。
    • 内核启用了 CONFIG_SYSFS 和 CONFIG_HOTPLUG。
  • 功能 :
    • bind:手动绑定设备到驱动,触发 probe()。
    • unbind:手动解绑设备,触发 remove()。

3. /sys/bus/platform/ 特殊文件

除了 devices/ 和 drivers/,platform 总线下还有:

  • drivers_autoprobe :控制是否自动绑定驱动(写 N 禁止自动匹配)。
  • drivers_probe:手动触发某个设备的驱动探测。
  • uevent :向用户空间发送设备事件(如 add/remove),常用于测试 udev 规则。

4. 总线分层与路径映射

  • platform vs pci :
    • platform:SoC 内部外设控制器(如 Rockchip 的 PCIe RC)。
    • pci:由 RC 初始化出来的标准 PCI 总线,挂载具体的 PCIe 设备。
    • 二者是父子关系:先有 platform 层的 RC,后有 pci 层的设备枚举。
  • I²C/SPI/MMC/USB :都是总线抽象,设备 ID 命名规则不同(I²C 的 0-0014,SPI 的 spi0.0,PCI 的 0000:01:00.0,USB 的 1-1.3:1.0)。

5. 常见总线的操作示例

Platform

bash 复制代码
echo fe150000.pcie > /sys/bus/platform/drivers/rk-pcie/unbind
echo fe150000.pcie > /sys/bus/platform/drivers/rk-pcie/bind

PCI

bash 复制代码
echo 0000:01:00.0 > /sys/bus/pci/drivers/nvme/unbind
echo 0000:01:00.0 > /sys/bus/pci/drivers/nvme/bind

I²C

bash 复制代码
echo 0-0014 > /sys/bus/i2c/drivers/goodix-ts/unbind
echo 0-0014 > /sys/bus/i2c/drivers/goodix-ts/bind

SPI

bash 复制代码
echo spi0.0 > /sys/bus/spi/drivers/m25p80/unbind
echo spi0.0 > /sys/bus/spi/drivers/m25p80/bind

USB

bash 复制代码
echo 1-1.2 > /sys/bus/usb/drivers/usb/unbind
echo 1-1.2 > /sys/bus/usb/drivers/usb/bind

USB-Serial

bash 复制代码
echo 1-1.3:1.0 > /sys/bus/usb-serial/drivers/pl2303/unbind
echo 1-1.3:1.0 > /sys/bus/usb-serial/drivers/pl2303/bind

MMC/SDIO

bash 复制代码
echo mmc1:0001 > /sys/bus/sdio/drivers/bcmdhd/unbind
echo mmc1:0001 > /sys/bus/sdio/drivers/bcmdhd/bind

HID

bash 复制代码
echo 0003:046D:C534.0001 > /sys/bus/hid/drivers/hid-generic/unbind
echo 0003:046D:C534.0001 > /sys/bus/hid/drivers/hid-generic/bind

Virtio

bash 复制代码
echo virtio0 > /sys/bus/virtio/drivers/virtio_net/unbind
echo virtio0 > /sys/bus/virtio/drivers/virtio_net/bind

SCSI

bash 复制代码
echo 0:0:0:0 > /sys/bus/scsi/drivers/sd/unbind
echo 0:0:0:0 > /sys/bus/scsi/drivers/sd/bind

Type-C

bash 复制代码
echo typec0 > /sys/bus/typec/drivers/typec/unbind
echo typec0 > /sys/bus/typec/drivers/typec/bind

MDIO

bash 复制代码
echo f1c00000.mdio:01 > /sys/bus/mdio_bus/drivers/<phy-driver>/unbind
echo f1c00000.mdio:01 > /sys/bus/mdio_bus/drivers/<phy-driver>/bind

其他总线

  • media 、mipi-dsi 、iio 、gpio 、soc 、rpmsg 、tee 、scmi_protocol 等总线的用法与上述类似:在 /sys/bus/<bus>/drivers/<driver>/ 下执行 echo 设备名到 unbind/bind。

6. 调试策略

  • 控制器问题 → 操作 platform/amba/soc 下的驱动。
  • 设备问题 → 操作 pci/i2c/spi/usb/mmc/scsi 等总线下的驱动。
  • 没有 bind/unbind 文件 → 驱动未实现 remove() 或为 built-in。
  • 重绑定影响范围 → platform 层重绑定可能重置控制器,会影响其下所有设备。
  • 日志观察 → 用 dmesg 监控 probe/remove 的打印,结合设备状态变化判断是否成功。

7. 总结

Linux 设备模型通过 sysfs 提供了统一的驱动绑定机制。不同总线类型(platform、PCI、I²C、SPI、USB、MMC、SCSI、HID、Virtio、Type-C 等)都可以支持 bind/unbind,前提是驱动按规范注册并实现了 probe/remove。在调试时要分清层次:

  • platform → 控制器本身
  • pci/i2c/spi/usb 等 → 总线设备

这样才能正确选择在哪个目录下执行 bind/unbind,避免混淆。

相关推荐
HideF10 小时前
Linux sudo
linux
FlightYe10 小时前
视界原理之3D视频(四):裸眼、眼镜和头显
android·linux·c++·3d·ffmpeg·音视频
蹊黎11 小时前
Linux 下用 C 语言实现进度条
linux·c语言·单片机
牛马鸡niumasi12 小时前
【Linux】C语言文件操作
linux
say_fall12 小时前
【Linux系统编程】Ext 文件系统:磁盘与存储、文件与目录、现代计算机究竟如何寻找文件
linux·运维·服务器·数据库·c++
wacsii13 小时前
【Linux进程(一)】Linux 进程初探:操作系统如何管理进程?fork() 为什么返回两次?
linux·运维·服务器
AI+程序员在路上13 小时前
RV1126B 上支持的模型及全流程应用--从CNN及语音到 LLMVLM 与跨平台选型
linux·c语言·人工智能
默|笙14 小时前
【Linux网络】传输层协议TCP(1)---TCP报文介绍
linux·网络·tcp/ip
相思难忘成疾14 小时前
从零搭建 Kubernetes 1.30 集群:kubeadm 部署一主多从实战(RHEL 9.3 + Docker + flannel)
linux·运维·kubernetes
用户41071920132514 小时前
用 systemd 从零做一个系统健康巡检服务:脚本、沙箱与磁盘满排查实战
linux·ubuntu