字符驱动核心是 file_operations 结构体:open/read/write/ioctl/release 各对应一个函数,注册后在 /dev 下生成设备节点;用户态 open/read/write/ioctl 系统调用最终调到这些函数;ioctl 用于用户态和驱动传命令和参数。
本文概述
字符驱动是 Linux 驱动入门,面试常考:字符驱动框架、file_operations、ioctl、主设备号、设备节点。回答要能写出最小骨架,并讲清用户态和内核态怎么交互。
核心要点
字符驱动骨架:register_chrdev 注册主设备号→class_create→device_create 生成 /dev 节点
file_operations 结构体把 open/read/write/ioctl 系统调用映射到驱动函数
ioctl 用于用户态发命令(如设置频率、读状态),命令用 _IO/_IOR/_IOW 宏编码
用户态 open() 打开 /dev/xxx,read/write 读写,ioctl 发控制命令
中断和工作队列在驱动里处理硬件事件,通过 wait_queue 或 poll 通知用户态

面试官考察点
这是驱动开发手到擒来的题。面试官看:①file_operations 是否填对;②主设备号和设备节点怎么生成;③ioctl 命令怎么定义。
回答思路
先给骨架代码,再讲注册流程,最后讲用户态怎么调用。
参考回答
驱动骨架。
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#define MY_MAJOR 200
static int my_open(struct inode *i, struct file *f) { return 0; }
static ssize_t my_read(struct file *f, char __user *buf, size_t cnt, loff_t *off) { return 0; }
static long my_ioctl(struct file *f, unsigned int cmd, unsigned long arg) { return 0; }
static struct file_operations fops = {
.owner = THIS_MODULE,
.open = my_open,
.read = my_read,
.unlocked_ioctl = my_ioctl,
};
static int __init my_init(void) {
register_chrdev(MY_MAJOR, "mydev", &fops);
/* class_create / device_create 生成 /dev/mydev */
return 0;
}
注册流程。
| 步骤 | 函数 | 作用 |
|---|---|---|
| 注册主设备号 | register_chrdev | 告诉内核这个主设备号归你 |
| 创建设备类 | class_create | 在 /sys/class 下建类 |
| 创建设备 | device_create | 自动在 /dev 下生成 mydev 节点 |
| 卸载 | unregister_chrdev | 反过来清理 |
ioctl 命令。用户态用 ioctl(fd, cmd, arg) 发命令,驱动里用 _IO/_IOR/_IOW 宏定义命令号:
#define CMD_SET_FREQ _IOW('k', 1, int)
#define CMD_GET_STATE _IOR('k', 2, int)
驱动 my_ioctl 里 switch(cmd) 处理不同命令,copy_to_user/copy_from_user 传数据。
用户态怎么用。
int fd = open("/dev/mydev", O_RDWR);
ioctl(fd, CMD_SET_FREQ, &freq);
read(fd, buf, len);
close(fd);

扫码关注





























