1. Linux字符设备驱动基础解析
字符设备驱动是Linux内核中最基础的设备驱动类型之一,它负责处理以字节流形式进行数据交换的设备。与块设备不同,字符设备没有固定的块大小,也不支持随机访问,典型的例子包括键盘、鼠标、串口等。
在Linux系统中,所有的设备访问都通过设备文件(位于/dev目录下)来完成。当用户程序对设备文件执行read()、write()等系统调用时,内核会将调用路由到对应的设备驱动程序中。字符设备驱动需要实现这些操作的具体行为。
注意:字符设备与块设备的关键区别在于数据访问方式。字符设备按字节流处理,而块设备以固定大小的块为单位操作,且支持缓存。
1.1 字符设备驱动核心结构
Linux内核使用struct cdev来表示一个字符设备。这个结构体定义在<linux/cdev.h>中,主要包含以下重要成员:
c复制struct cdev {
struct kobject kobj;
struct module *owner;
const struct file_operations *ops;
struct list_head list;
dev_t dev;
unsigned int count;
};
其中最关键的是ops指针,它指向一个file_operations结构体,这个结构体定义了驱动支持的各种操作函数:
c复制struct file_operations {
struct module *owner;
loff_t (*llseek) (struct file *, loff_t, int);
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
int (*open) (struct inode *, struct file *);
int (*release) (struct inode *, struct file *);
// 更多操作函数...
};
驱动开发者需要根据设备特性实现这些函数。例如,一个简单的串口驱动至少需要实现open、release、read和write这几个基本操作。
1.2 设备号与设备文件
Linux内核通过主设备号(major number)和次设备号(minor number)来唯一标识一个字符设备。主设备号用于标识设备类型(即对应的驱动程序),次设备号用于区分同一驱动程序管理的不同设备实例。
设备号使用dev_t类型表示,它是一个32位整数,其中高12位是主设备号,低20位是次设备号。内核提供了以下宏来处理设备号:
c复制MAJOR(dev_t dev); // 获取主设备号
MINOR(dev_t dev); // 获取次设备号
MKDEV(int major, int minor); // 通过主次设备号生成dev_t
在用户空间,可以通过mknod命令创建设备文件:
bash复制mknod /dev/mydevice c 250 0
这里`
