驱动程序除了需要提供读写设备能力之外,还需要提供控制设备的能力,这就需要用到ioctl方法。
1. ioctl方法
在应用层中,ioctl系统调用原型如下:
#include <sys/ioctl.h> int ioctl(int fd, unsigned long cmd, ...); fd: 文件描述符。 cmd: 控制命令。 第三个参数是可选的,具体由设备而定。
在内核层中,ioctl原型有两种(视内核版本而定);
2.6.36之前的内核是:
int (*ioctl) (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
2.6.36之后的内核是:
long (*unlocked_ioctl) (struct file *file, unsigned int cmd, unsigned long arg);
2. ioctl命令
ioctl中的命令实际上就是一个整数,但是为了使命令具有可读性,或者更多的信息,这个命令分成了几个部分:
type: 类型/幻数,8bit长度,表示属于那个设备的命令。 number: 序号,8bit长度,命令的序列号,用来区分不同的命令。 direction: 传输方向,参数的传输方向,有_IO_NONE、_IO_READ和_IO_WRITE。 size: 参数长度。
Linux提供了宏来定义命令:
_IO(type,nr): 用于构造无参数的命令。 _IOR(type,nr,datatype) 用于构造读参数的命令。 _IOW(type,nr,datatype) 用于构造写参赛的命令。 _IOWR(type,nr,datatype) 双向数据传输的命令。
在构造命令之前呢最后先阅读Documentation/ioctl/ioctl-number.txt,这个文件里面说明了已经使用了的幻数和命令序号(目的是为了定义一个唯一的命令)。
例如:
#define EXT4_IOC_GETVERSION _IOR('f', 3, long) #define EXT4_IOC_SETVERSION _IOW('f', 4, long) #define EXT4_IOC_MIGRATE _IO('f', 9)