Fundamentals 15 min read

Linux /sys/bus Explained: Kernel Device Bus Architecture and Practical Exploration

The article delves into the Linux /sys/bus directory of the sysfs virtual file system, detailing how the kernel registers bus types, organizes devices and drivers, explains core structures like struct bus_type, walks through the device‑add and driver‑probe workflow with concrete USB examples, and demonstrates practical inspection using NanoCode.

Linux Kernel Journey
Linux Kernel Journey
Linux Kernel Journey
Linux /sys/bus Explained: Kernel Device Bus Architecture and Practical Exploration

/sys/bus: organization by bus type

/sys/bus is a top‑level directory of the sysfs virtual file system that exposes every bus type registered in the kernel (e.g., usb, pci, platform). Each bus type is created by a struct bus_type instance registered with bus_register().

amba            cec
clockevents     clocksource
container       cpu
event_source    gadget
genpd           gpio
hid             i2c
iio             mdio_bus
media           mipi-dsi
mmc             mmc_rpmb
nvmem           pci
pci_express     platform
scmi_protocol   scsi
sdio            snd_seq
soc             spi
tee             typec
usb             workqueue

Entering a specific bus directory (e.g., /sys/bus/usb) shows the standard layout:

geduer@ulan:/sys/bus$ cd /sys/bus/usb
geduer@ulan:/sys/bus/usb$ ls
devices  drivers  drivers_autoprobe  drivers_probe  uevent

The devices subdirectory contains symbolic links to the real device nodes under /sys/devices. For USB, entries such as 5-1:1.0 and usb5 correspond to interface devices and the root hub:

1-0:1.0 -> ../../../devices/platform/usbdrd3_1/fc400000.usb/xhci-hcd.6.auto/usb1/1-0:1.0
2-0:1.0 -> ../../../devices/platform/usbdrd3_1/fc400000.usb/xhci-hcd.6.auto/usb2/2-0:1.0
…
usb5 -> ../../../devices/platform/fc880000.usb/usb5

The drivers subdirectory holds a directory per registered driver (e.g., usbhid, hub) and usually provides bind and unbind interfaces.

drwxr-xr-x 2 root root 0 Nov 5 17:35 asix
drwxr-xr-x 2 root root 0 Nov 5 17:35 cdc_acm
…
drwxr-xr-x 2 root root 0 Nov 5 17:35 usbtouchscreen

Kernel perspective: how /sys/bus is built

Core structure: struct bus_type

Each bus type is represented by a struct bus_type instance that defines the bus identity, matching rules, lifecycle callbacks, sysfs attributes and power‑management behavior. Using NanoCode, the structure can be inspected; for example, to view the spi_bus_type:

Run x lk!spi_bus_type to obtain the address.

Run dt lk!bus_type 0xffff8000`0aae35f8 to dump fields such as .name, .match, .probe, etc.

Bus registration: bus_register()

bus_register()

registers a new bus type, creates the corresponding sysfs entries and links the bus into the global bus_kset.

kset vs. klist

kset manages the sysfs hierarchy visible to user space, creating devices and drivers directories under /sys/bus/xxx.

klist manages internal kernel object lists with reference‑count protection, enabling safe traversal during hot‑plug, driver binding and module unload.

During bus registration the kernel:

Associates the bus’s kobject with the global bus_kset.

Creates child ksets devices_kset and drivers_kset for device and driver nodes.

Initialises klist_devices and klist_drivers for runtime tracking.

Device‑driver matching based on the bus

When a device is added, device_add() calls bus_probe_device(), which delegates matching to the bus’s .match function. If drivers_autoprobe is enabled, the kernel attempts to bind a suitable driver. driver_match_device() invokes the bus’s match(drv, dev) function.

On a successful match, driver_probe_device() executes the driver’s probe method via the chain

driver_probe_device() → __driver_probe_device() → really_probe() → call_driver_probe()

.

For a USB storage device the flow is: storage_probe() (USB storage driver entry) performs protocol selection, applies vendor quirks, and schedules an asynchronous thread.

The thread eventually calls sd_probe() in the SCSI subsystem, which creates scsi_disk and gendisk, queries capacity via SCSI commands, and registers the block device with device_add_disk(), making /dev/sdX visible.

NanoCode practice

A NanoCode script recursively traverses all bus directories under /sys/bus and lists each bus’s devices and drivers. A shortened excerpt for the USB bus:

usb5  0xffff0001078388a8         [usb: 0xffff80000aaed490]
│           │                     │                │
▼           ▼                     ▼                ▼
DeviceName  DeviceAddress          DriverName       DriverAddress

For the USB bus, the devices column lists entries such as usb5 with their kernel addresses, while the drivers column shows driver names like usbfs and their addresses.

usb5  0xffff0001078388a8
│           │
▼           ▼
DeviceName  DeviceAddress

usbfs     0xffff80000aaed318
│           │
▼           ▼
DriverName  DriverAddress

Using NanoCode’s dt command on a device address (e.g., dt lk!device 0xffff0001078388a8) displays the full struct device layout.

Command output for the USB bus is presented as a tree:

usb5  0xffff0001078388a8         [usb: 0xffff80000aaed490]
│           │                     │                │
▼           ▼                     ▼                ▼
设备名   设备地址(device)   关联的驱动名   关联驱动地址(device_driver)
usbfs     0xffff80000aaed318
│               │
▼               ▼
驱动名          驱动地址(device_driver)

Running dt lk!device 0xffff0001078388a8 shows the complete struct device fields.

Summary of the matching mechanism

The kernel does not let a device search for a driver; instead, the bus object actively matches devices to drivers using its .match callback, then invokes the driver’s probe via the call chain shown above. In the USB storage example, storage_probe() sets up an asynchronous task, sd_probe() creates the SCSI disk structures, and device_add_disk() registers the block device, exposing /dev/sdX to user space.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

kernelLinuxsysfsNanoCodebus_typedevice busdriver matching
Linux Kernel Journey
Written by

Linux Kernel Journey

Linux Kernel Journey

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.