
一、字符设备(以字节为单位进行输入输出)
字符设备没有固定的大小,也没有缓冲区,数据会立即被传输。

字符设备驱动通过面向流的 I/O 接口,以字节流传输机制实现用户空间程序与设备之间的异步数据交互。此类设备在 Linux 系统中遵循 "Everything is a file" 的核心设计哲学,通过虚拟文件系统(VFS)框架在 /dev 目录下创建设备文件节点。
在内核实现层面,字符设备驱动以 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;
};1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
1、字符设备驱动的核心特点
- 像文件一样使用:字符设备在 Linux 中被当作普通文件处理,用户可以通过读(read)、写(write)等文件操作命令直接与设备交互。
- 功能简单直接:主要处理单个字节或连续数据流(比如串口、键盘),不涉及复杂的数据块管理。
- 模块化开发:驱动通常以内核模块形式存在,可以动态加载/卸载。
2、如何创建和注册字符设备
创建设备的步骤
- 分配设备号:每个设备都有唯一编号(主设备号 + 次设备号)。
- 创建设备文件:用户通过
mknod命令在文件系统中生成对应的设备文件。
注册到系统
- 定义功能接口:用
file_operations结构体列出设备支持的操作。 - 调用注册函数:用
register_chrdev或register_chrdev_region告诉内核这个设备的存在。
3、设备文件方法
内核通过 struct file_operations 结构,将设备功能包装成标准文件操作:
c
struct file_operations {
int (*open)(设备, 参数); // 打开设备时触发
int (*read)(设备, 数据缓冲区); // 用户读数据时调用
int (*write)(设备, 数据缓冲区); // 用户写数据时调用
// 还有 close、ioctl 等其他方法...
};1
2
3
4
5
6
2
3
4
5
6
总结
字符设备驱动 = 功能函数(如读写操作) + 设备注册(告诉内核设备存在) + 设备文件(让用户可见)。用户只需像操作普通文件一样,就能通过系统调用间接调用驱动中的功能。
二、块设备
硬盘、U 盘属于块设备,以块为单位进行输入输出。块设备有缓冲区,数据下发以后会在缓冲区中缓存。块设备可以被分区,还可以格式化文件系统。

块设备主要有以下两种:
- 机械硬盘:读写单位是扇区。访问机械硬盘时需要首先移动磁头寻找磁道,然后转动盘片找到扇区。
- 闪存类块设备:使用闪存作为存储介质。常见的闪存类块设备包括固态硬盘(SSD)、嵌入式多媒体存储卡(eMMC)和通用闪存存储(UFS)。
闪存(Flash Memory)的主要特点:
- 在写入数据之前需要擦除一个擦除块
- 一个擦除块的最大擦除次数有限(NOR 约 10^4~10^5 次,NAND 约 10^5~10^6 次)
三、网络设备
