1. VxWorks字符设备驱动基础
1.1 字符设备驱动概念
字符设备驱动是 VxWorks 中最基础、最常用的驱动类型。它管理那些以顺序字节流方式访问的硬件设备,例如串口、GPIO、I2C、SPI 等。与块设备不同,字符设备不支持随机访问和缓冲,每次读写操作直接作用于硬件寄存器或 FIFO。
核心特征:
- 顺序访问:数据按字节流顺序处理,不支持 lseek 随机定位。
- 无缓冲:读写操作直接穿透到硬件,不经过系统缓冲区。
- 同步/异步:支持阻塞和非阻塞两种 I/O 模式。
- 设备文件:通过文件系统路径(如
/tyCo/0)暴露给用户态。
在 VxWorks 中,字符设备驱动通过注册一组标准函数指针(称为 驱动表)来实现。用户态任务通过标准的 POSIX 接口(open、read、write、ioctl、close)与驱动交互,驱动内部再映射到具体的硬件操作。
1.2 VxWorks I/O 系统架构
VxWorks 的 I/O 系统采用分层架构,从上到下依次为:应用层、文件系统层、I/O 子系统层、驱动层和硬件层。每一层都有明确的职责和接口契约。
| 层次 | 组件 | 职责 |
|---|---|---|
| 应用层 | 用户任务 | 调用 open()、read()、write() 等 API |
| 文件系统层 | dosFs、rawFs、romFs 等 | 提供文件目录结构,管理文件元数据 |
| I/O 子系统 | iosLib | 维护文件描述符表、驱动表、设备表,分发 I/O 请求 |
| 驱动层 | 字符设备驱动 | 实现 xxOpen()、xxRead()、xxWrite() 等回调 |
| 硬件层 | 外设寄存器 | 物理硬件操作,中断处理 |
I/O 子系统(iosLib)是 VxWorks I/O 架构的核心。它维护三个关键数据结构:
- 文件描述符表:每个任务私有,记录打开的文件描述符与设备/文件的映射。
- 驱动表:全局唯一,存储每个驱动号的
DRV_ENTRY结构体,包含 7 个标准函数指针。 - 设备表:全局唯一,存储每个设备名与驱动号的关联。
关键点:VxWorks 的 I/O 子系统不区分“字符设备”和“块设备”的驱动注册方式。所有驱动都通过
iosDrvInstall() 注册到驱动表,区别在于实现哪些回调函数。字符设备通常实现 open、close、read、write、ioctl,而块设备额外需要 blkRd、blkWrt。
1.3 设备驱动与文件系统关系
在 VxWorks 中,设备驱动与文件系统的关系通过设备文件来建立。设备文件是文件系统中的一个特殊节点,它不存储实际数据,而是指向一个具体的硬件设备。用户态任务通过操作设备文件来间接控制硬件。
设备驱动的注册流程通常包含以下步骤:
- 驱动初始化:调用
iosDrvInstall()注册驱动回调函数,返回驱动号。 - 设备创建:调用
iosDevAdd()将设备名与驱动号关联,添加到设备表。 - 文件系统挂载:设备文件出现在文件系统目录树中(如
/dev/)。 - 用户访问:任务通过
open("/dev/xxx", ...)打开设备文件,触发驱动回调。
/* 字符设备驱动注册示例 */
STATUS myDrvInit(void)
{
int drvNum;
/* 1. 注册驱动回调 */
drvNum = iosDrvInstall(myOpen, /* open */
myClose, /* close */
myRead, /* read */
myWrite, /* write */
myIoctl, /* ioctl */
NULL, /* delete (unused) */
NULL); /* select (unused) */
if (drvNum == ERROR)
return ERROR;
/* 2. 创建设备节点 */
if (iosDevAdd(&myDevHdr, "/dev/myDev", drvNum) == ERROR)
return ERROR;
return OK;
}
设备文件与普通文件的区别:
| 特性 | 普通文件 | 设备文件 |
|---|---|---|
| 数据存储 | 存储在磁盘/Flash | 无存储,映射到硬件寄存器 |
| 访问方式 | 通过文件系统缓存 | 直接穿透到驱动 |
| 生命周期 | 持久化存在 | 随驱动加载/卸载 |
| 并发访问 | 文件系统提供锁保护 | 驱动开发者自行管理 |
| ioctl 支持 | 有限 | 核心控制接口 |
常见陷阱:初学者容易混淆“设备文件”和“普通文件”的并发语义。普通文件在 VxWorks 文件系统层有内置的读写锁保护,而设备文件没有任何默认的并发保护。如果多个任务同时
write() 同一个字符设备,驱动回调函数可能被并发执行,导致寄存器竞争、数据错乱甚至系统崩溃。这正是本课程后续章节要深入探讨的锁机制问题。
1.4 本章小结
本章建立了字符设备驱动的基础知识框架:
- 字符设备驱动以顺序字节流方式访问硬件,无缓冲、无随机访问。
- VxWorks I/O 系统采用五层架构,I/O 子系统(iosLib)是核心分发器。
- 设备驱动通过设备文件与文件系统关联,用户态任务通过标准文件接口操作硬件。
- 字符设备驱动没有默认的并发保护,驱动开发者必须自行实现锁机制。