Linux设备驱动程序学习(4)
-高级字符驱动程序操作[(1)ioctl and llseek]
今天进入《Linux设备驱动程序(第3版)》第六章高级字符驱动程序操作的学习。
一、ioctl
大部分设备除了读写能力,还可进行超出简单的数据传输之外的操作,所以设备驱动也必须具备进行各种硬件控制操作的能力. 这些操作常常通过ioctl 方法来支持,它有和用户空间版本不同的原型:
需要注意的是:不管可选的参数arg是否由用户给定为一个整数或一个指针,它都以一个unsigned long 的形式传递。如果调用程序不传递arg参数, 被驱动收到的arg 值是未定义的。因为在arg参数上的类型检查被关闭了,所以若一个非法参数传递给ioctl,编译器是无法报警的,且任何关联的错误难以查找.
选择ioctl命令
为了防止向错误的设备使用正确的命令,命令号应该在系统范围内唯一。为方便程序员创建唯一的ioctl 命令代号,每个命令号被划分为多个位字段。要按Linux 内核的约定方法为驱动选择ioctl 的命令号, 应该首先看看include/asm/ioctl.h 和Documentation/ioctl-number.txt。要使用的位字段符号定义在:
type(幻数):8 位宽(_IOC_TYPEBITS),参考ioctl-number.txt选择一个数,并在整个驱动中使用它。
number(序数):顺序编号,8 位宽(_IOC_NRBITS)。
direction(数据传送的方向):可能的值是_IOC_NONE(没有数据传输)、_IOC_READ、_IOC_WRITE 和_IOC_READ|_IOC_WRITE (双向传输数据)。该字段是一个位掩码(两位), 因此可使用AND 操作来抽取_IOC_READ 和_IOC_WRITE。
size(数据的大小):宽度与体系结构有关,ARM为14位.可在宏_IOC_SIZEBITS 中找到特定体系的值.
中包含的定义了一些构造命令编号的宏: