本文共 1168 字,大约阅读时间需要 3 分钟。
大部分驱动程序除了读写功能外,还需要具备控制设备的能力,比如对于串口,需要具备修改波特率的功能。
在用户空间,使用ioctl()函数作为系统调用来控制设备原型:int ioctl(int fd,unsigned long cmd,...)头文件:功能:字符设备控制函数参数:fd:要控制的设备文件描述符 cmd:发送给设备的控制命令 ...:第3个参数是可选的参数,存在与否是依赖于控制命令(第2个参数 )。
当应用程序使用ioctl系统调用时,驱动程序的响应函数根据Linux版本不同将由不同函数来响应:
①2.6.36 之前的内核long (*ioctl) (struct inode* node ,struct file* filp, unsigned int cmd,unsigned long arg)
②2.6.36之后的内核
long (*unlocked_ioctl) (struct file *filp, unsigned int cmd, unsigned long arg)
实现设备控制函数编写主要有两步:
1.定义命令2.实现设备方法,即编写实现命令的unlocked_ioctl函数
命令从其实质而言就是一个整数, 但为了让这个整数具备更好的可读性,我们通常会把这个整数分为几个段:类型(8位),序号,参数传送方向,参数长度。 ①Type(类型/幻数):表明这是属于哪个设备的命令 ②Number(序号):用来区分同一设备的不同命令 ③Direction:参数传送的方向,可能的值是 _IOC_NONE(没有数据传输),_IOC_READ,_IOC_WRITE(向设备写入参数) ④Size: 参数长度为了开发容易,Linux系统提供了下面的宏来帮助定义命令:
①_IO(type,nr):不带参数的命令 ②_IOR(type,nr,datatype):从设备中读参数的命令 ③_IOW(type,nr,datatype):向设备写入参数的命令 例:#define MEM_MAGIC 'm' //定义幻数#define MEM_SET _IOW(MEM_MAGIC, 0, int)
一个字符正好是8位,所以可以用一个字符来表示类型,这显得较为简略;int表示传输的参数是int类型的。
unlocked_ioctl函数的实现通常是由switch语句完成。但是,当命令号不能匹配任何一个设备所支持的命令时,返回-EINVAL。
编程模型:switch(cmd){ case 命令A: return 0; case 命令B: return 0; default: return -EINVAL;}
转载地址:http://irigi.baihongyu.com/