<aside> 💡 在之前的字符设备驱动实验中,使用了 register_chrdev 来注册设备驱动,但是这个接口自动会为主设备占用掉 256 个次设备的资源,而使用其他接口手动注册的方式则可以节省这些资源。

</aside>

1. 字符设备驱动内部实现框图

Untitled

  1. 所有的 Linux 文件都有一个自己的 inode 号,通过 ls -i 可以查看
  2. 驱动设备文件也不例外,这个 inode 号对应内核内存中的 inode 结构体:linux/fs.h 中的 inode 结构体源码
  3. inode 结构体中有一个 dev_t i_rdev 的属性,这个属性是一个指针,执行驱动的结构体,例如字符设备驱动 cdev 结构体:linux/cdev.h 的源码
  4. cdev 结构体拥有 file_operations 的属性,它保存了驱动的读写等回调方法

详细分析见第 5,第 6 小节。

2. 字符设备驱动分步注册步骤

  1. 为字符设备驱动对象申请空间
  2. 初始化字符设备驱动对象
  3. 注册字符设备驱动对象
  4. 注销字符设备驱动对象

3. 相关 API

相关的 API 接口都在 #include <linux/cdev.h>

3.1 驱动对象结构体

linux/include/linux/cdev.h at master · torvalds/linux

struct cdev {
    struct kobject kobj;
    struct module *owner;// 模块对象指针  THIS_MODULE
    const struct file_operations *ops;// 操作方法结构体指针
    struct list_head list;// 用于构成链表的成员
    dev_t dev;// 设备号
    unsigned int count;// 设备资源数量
}

3.2 字符设备驱动对象申请空间

struct cdev cdev; // 栈区
struct cdev *cdev_alloc(void); // 堆区

功能:手动申请字符设备驱动对象空间

参数:无

返回值:成功返回申请到的对象空间首地址,失败返回 NULL

3.3 初始化设备驱动对象