linux内核如何列举外设
linux内核如何列举外设详细介绍
在 Linux 内核中,列举外设主要通过设备模型(Device Model)和sysfs 文件系统实现,同时内核提供了一系列函数用于遍历和操作设备。以下分用户空间和内核空间两种场景说明:
一、用户空间:通过 sysfs 和工具列举外设
1.
sysfs 文件系统(核心接口)
sysfs 位于/sys目录下,按总线类型、设备类别等组织设备信息,常用路径:
- 所有设备的层次结构:bash
/sys/devices//sys/devices/
- 按总线类型列举(如 PCI、USB、平台设备):bash
/sys/bus/pci/devices//sys/bus/usb/devices/
/sys/bus/platform/devices/
/sys/bus/bus_type/devices/
- 按设备类别(Class)列举(如块设备、字符设备、网络设备):bash
/sys/class/block//sys/class/net/
/sys/class/class_name/
2.
常用工具
- 通用设备列举:bash
lsusblspci
lsblk
- 详细设备信息:
进入设备目录(如/sys/devices/pci0000:00/0000:00:14.0/),查看name、vendor、device等属性文件。
二、内核空间:通过内核函数遍历外设
内核提供了一套设备模型 API,用于遍历总线、设备和驱动。以下是常见场景:
1.
遍历指定总线下的所有设备
- 通用方法(适用于所有总线):
使用bus_for_each_dev函数,遍历总线struct bus_type下的所有设备:
cbus pci_bus_type
ret bus data callback
其中
callback是自定义处理函数,参数为struct device *dev。 - 示例:遍历 PCI 设备(头文件
linux/pci.h):
ccallback datapdev
pdev
pdevvendor VENDOR_ID pdevdevice DEVICE_ID
2.
遍历平台设备(Platform Device)
平台设备在内核中通过platform_bus管理,使用device_for_each_child函数:
c
parent platform_bus
parent data callback
3.
按设备类别(Class)遍历
通过class_for_each_device函数遍历属于某个类的设备:
c
cls
cls data callback
4.
设备结构体struct device
每个设备对应一个struct device,包含关键信息:
c
devbusdevdriver
devparent
devkobjname
三、不同总线类型的特殊处理
1.
PCI 设备
- 头文件:
linux/pci.h - 核心结构体:
struct pci_dev,包含 PCI 特定信息(如 BAR 空间、PCI 配置空间)。 - 函数:
pci_get_device(按 Vendor/Device ID 查找设备)、pci_enum_devices(枚举所有设备)。
2.
USB 设备
- 头文件:
linux/usb.h - 核心结构体:
struct usb_device,包含 USB 描述符、端点等信息。 - 函数:
usb_for_each_dev(遍历所有 USB 设备)。
3.
平台设备(Platform Device)
- 头文件:
linux/platform_device.h - 核心结构体:
struct platform_device,用于非标准总线设备(如板载外设)。 - 遍历:通过
platform_bus的设备链表(见上文示例)。
四、总结
- 用户空间:主要通过
sudo访问/sys目录或使用lsusb、lspci等工具,利用 sysfs 暴露的设备模型信息。 - 内核空间:根据总线类型(PCI/USB/ 平台设备等),使用对应的遍历函数(如
pci_for_each_dev、bus_for_each_dev),操作struct device或其派生结构体(如struct pci_dev)。
实际开发中,需根据外设所属的总线类型选择具体接口,并注意内核版本兼容性(部分函数在旧内核中可能不同)。