字符设备注册、CDev 与 Misc 框架

字符设备注册、CDev 与 Misc 框架

1. Dev_t

字符设备由dev_t标识:

1
2
major -> 驱动/分发表
minor -> 实例或子功能

静态major用于兼容ABI;新驱动通常alloc_chrdev_region()动态分配。

2. CDev

标准注册:

1
2
3
4
5
alloc_chrdev_region
-> cdev_init(&cdev, &fops)
-> cdev_add(devt, count)
-> class_create
-> device_create

cdev_add()建立dev_t到cdev的kobject映射。device_create()只建立device model/sysfs和devtmpfs事件,二者不是同一动作。

注销逆序:

1
2
3
4
device_destroy
-> class_destroy
-> cdev_del
-> unregister_chrdev_region

必须先阻止新open,并保证已有fd的私有对象仍存活。

3. Open分发

fs/char_dev.c中的chrdev_open()

  1. 从inode dev_t查找cdev;
  2. 缓存inode->i_cdev
  3. 增加cdev/module引用;
  4. 替换file->f_op
  5. 调用具体driver .open

后续read/write/ioctl直接进入具体fops。

4. register_chrdev

Legacy接口可一次注册整个major。Driver open再按minor分发。mem.c、virtio_console等仍使用该接口。

新多实例driver更适合明确的region+cdev,便于生命周期和sysfs对应。

5. Misc框架

misc.c固定注册major 10并维护misc list。Driver:

1
2
3
4
5
6
struct miscdevice {
int minor;
const char *name;
const struct file_operations *fops;
...
};

调用misc_register()

  • MISC_DYNAMIC_MINOR从bitmap分配;
  • 加入全局list;
  • device_create_with_groups()
  • 默认node名来自namenodename

6. Misc Open

所有misc node先进入misc_open()

  1. 取inode minor;
  2. 在misc list查找;
  3. 请求模块;
  4. file->f_op替换为目标fops;
  5. file->private_data设为miscdevice;
  6. 调目标.open

Driver若覆盖private_data,需理解这个初始值。

7. 并发和引用

注册表由mutex保护,但registry锁不保护driver内部状态。Driver需自己处理:

  • 多open;
  • remove与fd并发;
  • ioctl和read并发;
  • blocking wait;
  • mmap在close后仍存在;
  • module卸载。

.owner = THIS_MODULE只保护模块代码,不自动保护platform私有内存。

8. File Private Data

常见模式:

1
2
3
4
5
6
7
8
9
open:
container_of(inode->i_cdev)
allocate file context
file->private_data = ctx

release:
cancel waits
put device reference
free ctx

每fd状态不要误放到全局device结构中,否则多个进程会互相覆盖offset、mode或pending command。

9. Poll

1
2
3
poll_wait(file, &waitq, table)
-> check readable/writable/error state
-> return EPOLLIN/OUT/ERR/HUP

状态更新后必须先改变受锁保护的条件,再wake_up_interruptible_poll(),避免丢唤醒。

10. Compat IOCTL

64位RK3588运行32位应用时会进入.compat_ioctl。含pointer、long、alignment或可变数组的结构不能直接复用native布局。

Ioctl命令必须验证:

  • magic和number;
  • direction/size;
  • integer range;
  • user pointer;
  • reserved bits;
  • capability和device state。

文章互动

阅读 --

留言

0 条留言

正在加载留言…