Linux Workshop Adventure: Exploring Buses, Devices, and Drivers

Linux Workshop Adventure: Exploring Buses, Devices, and Drivers
Click the blue text above to follow me and read beautiful articles.
Linux Workshop Adventure: Exploring Buses, Devices, and Drivers

The Linux operating system’s kernel manages various hardware devices in the system, including buses, devices, and drivers. This article will introduce the basic concepts of buses, devices, and drivers in the Linux system, as well as their relationships. By combining relevant /sys directory structures, readers will better understand the hardware management mechanism in the Linux system.

Linux Workshop Adventure: Exploring Buses, Devices, and Drivers
Data Structures

Buses play a bridging role in computer systems, responsible for connecting the CPU, memory, devices, and other hardware components, allowing them to communicate and cooperate with each other. In Linux systems, common types of buses include PCI, USB, SATA, etc., each with its specific uses and characteristics.

/* Bus Data Structure */
struct bus_type {
    const char *name;               // Name of the bus type
    struct device *dev_root;        // Pointer to the head of the linked list of all devices on this bus
    const char *drvsubdir;          // Name of the subdirectory storing device drivers
    const struct attribute_group **bus_groups;   // Attribute groups of the bus type
    const struct attribute_group **dev_groups;   // Attribute groups of all devices on the bus
};

In the Linux system, each device has a unique identifier, which can be accessed through the /sys/devices directory. The subdirectories under this directory represent various devices in the system, each containing the attribute information and status of the device.

/* Device Data Structure */
struct device {
    struct kobject kobj;            // Kernel object for managing device attributes
    const char *init_name;          // Name of the device
    struct bus_type *bus;           // Pointer to the bus where the device is located
    struct device *parent;          // Pointer to the parent device
    struct device_driver *driver;   // Pointer to the driver used by the device
    const struct attribute_group **groups;      // Attribute groups of the device
    struct device_node *of_node;    // Pointer to the device tree node
};

Device drivers are software components that communicate with devices in the system, responsible for controlling device operations and management. In Linux systems, drivers are typically loaded into the kernel as modules and manage driver and device information related to buses through the /sys/bus directory.

/* Driver Data Structure */
struct device_driver {
    const char *name;               // Name of the driver
    struct bus_type *bus;           // Pointer to the bus where the driver is located
    struct module *owner;           // Pointer to the kernel module owning this driver
    const char *mod_name;           // Name of the kernel module where the driver is located
    int (*probe)(struct device *dev);   // Function pointer to probe the device
    int (*remove)(struct device *dev);  // Function pointer to remove the device
    void (*shutdown)(struct device *dev);   // Function pointer to shut down the device
    const struct attribute_group **groups;  // Attribute groups of the driver
};

Device categories are classified based on device functions or features, such as network devices, block devices, etc. In the Linux system, device category information can be accessed through the /sys/class directory, where each category corresponds to a subdirectory containing information about multiple devices of the same category.

struct class {
    const char *name;                     // Name of the category
    struct module *owner;                 // Pointer to the kernel module owning this category
    struct class_attribute *class_attrs;  // List of category attributes
    struct device_attribute *dev_attrs;   // List of device attributes
    struct bin_attribute *dev_bin_attrs;  // List of device binary attributes
    struct kobject *dev_kobj;             // Device objects under the category
    ...
};

The relationship between buses, drivers, and devices is shown in the figure below:

Linux Workshop Adventure: Exploring Buses, Devices, and Drivers

Linux Workshop Adventure: Exploring Buses, Devices, and Drivers
Virtual Files

The /sys directory is a virtual file system provided by the Linux kernel, used to dynamically present information about devices, buses, and drivers in the current system. This virtual file system is generated by the kernel based on data structures of devices, buses, and drivers, containing attribute information from these data structures.

These structures are closely related to the /sys directory in Linux, as the /sys directory is a virtual file system provided by the Linux kernel to dynamically present information about devices, buses, and drivers in the current system. This virtual file system is generated by the kernel based on data structures of devices, buses, and drivers, containing attribute information from these data structures.

Specifically, the /sys/bus directory contains subdirectories for all bus types registered with the kernel, where each subdirectory corresponds to a bus type, for example, /sys/bus/usb stores information related to the USB bus.

The /sys/devices directory contains all devices in the system, where each device corresponds to a subdirectory containing various attributes of the device, for example: /sys/devices/pci0000:00/0000:00:01.0 stores information about a PCI device.

The /sys/class directory contains device categories, where each category corresponds to a subdirectory, for example, /sys/class/net stores information about network devices.

The /sys/module directory contains modules loaded into the kernel, where each module corresponds to a subdirectory containing various attributes of the module, for example, /sys/module/usbcore stores information about the USB core module.

Below is a simple example code demonstrating how to register a bus named example_bus:

#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>

// Define bus type structure
static struct bus_type example_bus = {
    .name = "example_bus", // Name of the bus type
};

static int __init example_bus_init(void)
{
    int ret;

    // Register bus type
    ret = bus_register(&example_bus);
    if (ret)
        return ret;

    // Create and register devices on the bus
    // Omitted the process of creating and registering devices

    return 0;
}

static void __exit example_bus_exit(void)
{
    // Unregister bus type
    bus_unregister(&example_bus);
}

module_init(example_bus_init);
module_exit(example_bus_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("Example bus driver");

After registering the bus, a new subdirectory appears under the /sys/bus directory, corresponding to the name of the registered bus type. For example, if a bus type named example_bus is registered, a subdirectory named example_bus will appear under the /sys/bus directory.

In the new bus type subdirectory, it usually contains the following:

devices/: This directory contains information about all devices connected to this bus, with each device corresponding to a subdirectory.

drivers/: This directory contains information about drivers related to this bus type, with each driver corresponding to a subdirectory.

In summary, /sys/devices, /sys/bus, and /sys/class represent different organizational methods for organizing hardware device information in the /sys virtual file system. Each method has its specific uses and organizational structures:

  • /sys/devices: This is the most basic method, centered on devices, where each device corresponds to a subdirectory containing various attribute information about that device. This method is suitable for scenarios where management and operation are conducted on a device basis.

  • /sys/bus: This method is centered on bus types, where each bus type corresponds to a subdirectory containing information about devices connected to that bus. This method is suitable for scenarios where management and operation are conducted based on bus types, such as USB buses, PCI buses, etc.

  • /sys/class: This method is centered on device categories, where each device category corresponds to a subdirectory containing information about multiple devices of the same category. This method is suitable for scenarios where management and operation are conducted based on device categories, such as network devices, block devices, etc.

Therefore, these three organizational methods are suitable for different management and operation needs, allowing users to choose the appropriate method to access and manage hardware device information in the system based on actual conditions.

Linux Workshop Adventure: Exploring Buses, Devices, and Drivers
END
Linux Workshop Adventure: Exploring Buses, Devices, and Drivers
Looking forward to growing together with you
Linux Workshop Adventure: Exploring Buses, Devices, and Drivers
Linux Workshop Adventure: Exploring Buses, Devices, and Drivers
Linux Workshop Adventure: Exploring Buses, Devices, and Drivers
WeChat ID: Linux Workshop

Leave a Comment