05-字符设备驱动之ioctl
在04-最简单的字符设备驱动这篇文章中介绍了一个简单的字符设备驱动,包含了4个基本系统调用:open
、close
、read
、write
。其中read
、write
可以在应用空间和内核空间交换数据。但是某些操作不太适合他们来实现。比如:
- 清空kBuf
- 设置kBuf的操作行为
- 读取kBuf的属性,比如里面有多少有效数据等等。
这些操作不是"读数据"或"写数据",而是"控制设备"。此时我们就需要另一个系统调用,ioctl
来实现"控制设备"。
ioctl 的作用
ioctl = I/O Control(输入/输出控制)
read/write → 数据传输(data transfer),同一类数据。
ioctl → 设备控制(device control),可以传输各种不同的数据,相关参数可以起到解析数据的提示作用。
用户空间的 ioctl 调用
#include <sys/ioctl.h>
int ioctl(int fd, unsigned long cmd, ...);
参数:
- fd:文件描述符(open() 返回的)
- cmd:命令编号(你自己定义)
- ...:可选参数(根据命令不同)
ioctl参数cmd的定义
ioctl的参数cmd是一个 32位整数,包含多个字段:
31 30 29 16 15 8 7 0
┌───────────┬─────────┬─────────┬─────────┐
│ dir │ size │ type │ nr │
└───────────┴─────────┴─────────┴─────────┘
方向 数据大小 魔数 编号
(2位) (14位) (8位) (8位)
字段说明:
nr
(number):命令编号(0-255)type
:魔数(幻数),标识你的驱动,防止将别的驱动定义的ioctl命令用于操作此驱动,避免混淆,比如A驱动定义了一个用于复位的命令:A_CMD_RESET, B驱动定义了一个用于清空缓存区的命令:B_CMD_CLEAN,假设它们除了type不同,其他都一样,万一不小心把B_CMD_CLEAN用到A驱动上,你会觉得很差异,因为从宏的字面意思来看,你认为你在做清空缓存操作,结果设备无任何反应。size
:传输数据的大小dir
(direction):数据方向_IOC_NONE
:无数据传输_IOC_READ
:从驱动读取数据到用户空间_IOC_WRITE
:从用户空间写入数据到驱动_IOC_READ|_IOC_WRITE
:双向