Linux内核中通过device_add()注册/dev/设备节点的流程解析

ChatGPT4o 使用 ChatGPT 4o 回答

问题:

linux内核中是如何通过device_add()注册一个/dev/下的设备节点的?函数调用流程是怎样的?

回答:

在Linux内核中,通过device_add()函数注册一个设备节点的过程涉及多个步骤和函数调用。以下是一个简化的流程,描述了主要的函数调用和操作:

  1. 调用device_add():

    • 设备驱动程序调用device_add()函数来注册一个设备。
    • 该函数的原型为:
      int device_add(struct device *dev);
      
  2. 初始化设备结构体:

    • device_add()会对传入的struct device结构体进行一系列初始化操作,包括设置设备的状态、初始化设备的kobject等。
  3. 调用device_initialize():

    • device_add()内部会调用device_initialize()来初始化设备的kobject和其他相关字段。
  4. 调用bus_add_device():

    • device_add()会调用bus_add_device()将设备添加到总线(bus)上。
    • 这一步会将设备添加到总线的设备列表中,并触发总线的add回调函数。
  5. 调用device_create_file():

    • device_add()会调用device_create_file()为设备创建属性文件(sysfs文件),这些文件通常位于/sys/devices/目录下。
  6. 调用kobject_uevent():

    • device_add()会调用kobject_uevent()发送uevent通知用户空间,告知有新设备添加。
    • 这通常会触发udev等用户空间守护进程来创建相应的设备节点。
  7. 调用devtmpfs相关函数:

    • 如果启用了devtmpfs,内核会自动在/dev/目录下创建设备节点。
    • 具体来说,device_add()会调用devtmpfs_create_node()来创建设备节点。
  8. 设备节点创建:

    • devtmpfs_create_node()会根据设备的主次设备号(major/minor number)在/dev/目录下创建相应的设备节点文件。

以下是一个简化的调用流程图:

device_add()
    |
    +--> device_initialize()
    |
    +--> bus_add_device()
    |       |
    |       +--> bus->add(dev)
    |
    +--> device_create_file()
    |
    +--> kobject_uevent()
    |
    +--> devtmpfs_create_node()

代码示例

以下是一个简化的代码示例,展示了如何使用device_add()注册一个设备:

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

static struct class *example_class;
static struct device *example_device;
static dev_t devt;

static int __init example_init(void)
{
    int ret;

    // 分配设备号
    ret = alloc_chrdev_region(&devt, 0, 1, "example");
    if (ret < 0) {
        pr_err("Failed to allocate chrdev region\n");
        return ret;
    }

    // 创建设备类
    example_class = class_create(THIS_MODULE, "example_class");
    if (IS_ERR(example_class)) {
        unregister_chrdev_region(devt, 1);
        return PTR_ERR(example_class);
    }

    // 创建设备
    example_device = device_create(example_class, NULL, devt, NULL, "example_device");
    if (IS_ERR(example_device)) {
        class_destroy(example_class);
        unregister_chrdev_region(devt, 1);
        return PTR_ERR(example_device);
    }

    pr_info("Example device created successfully\n");
    return 0;
}

static void __exit example_exit(void)
{
    device_destroy(example_class, devt);
    class_destroy(example_class);
    unregister_chrdev_region(devt, 1);
    pr_info("Example device removed\n");
}

module_init(example_init);
module_exit(example_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Example Author");
MODULE_DESCRIPTION("Example Device");

在这个示例中,device_create()函数内部会调用device_add()来注册设备,并最终在/dev/目录下创建一个名为`example