第30章IOCTL函数
30-1:ioctl函数的作用:
设备在运行的时候可能要求数据的写入是连续的,如果这个时候仍然用WRITE函数去写指令的话,就有可能导致数据的不连续,比如声卡放音乐卡顿,电影播放不流畅等等的情况,为了解决这种情况,就有了IOCTL函数,此函数专门向驱动层发送或者接收指令。
30-2:ioctl函数的头文件和函数原型:
1) 应用层头文件:#include
int ioctl(int d,int request, ...)
作用:配合驱动层的IOCTL函数实现指令的传递
参数1:设备描述符
参数2:指令,如某一个命令对应驱动层的某一个功能
参数3:可变参数,跟命令有关,传递进入驱动层的参数或者是接收数据的缓存
返回成功:0
返回失败:小于0 返回值取决于用户如何设计驱动层
2) 驱动层头文件:#include
long (*unlocked_ioctl) (struct file *, unsigned int,unsigned long)
作用:此函数指针原型位于struct file_operations结构体当中,配合应用层ioctl函数实现指令传递的功能
参数1:文件结构体指针
参数2:指令
参数3:应用层传递给驱动层的数据或者是接收数据用到的缓存地址
30-3:ioctl函数的实现方法:
最基本的实现方法请参考代码和视频
得到一个结论:不能传递2,这是因为2已经被系统的其他程序占用了作为一个专用命令,所以在ioctl当中不能使用2,作为命令,于此相同情况的还不止2。正因为此原因,IOCTL不能够直接使用数字作为命令进行传递,而是有一套专门制作IOCTL命令的方法。
30-4:关于ioctl函数的命令:
30-5:系统提供的IOCTL命令工具:
Iotrl的系统定义命令方法是定义为一个32bit的无符号整形数字,这个数字会按位进行分段,每一段的含义都不一样,所以IOCTL的命令是四个部分组合起来形成的一个32bit的数字
最高2bit:读写控制位,读,写,有没有数据传输,双向传输(先写后读)
16bit—29bit:要传输的数据大小
8bit—15bit:魔数/幻数,其实就是不同组命令的区分标识,写入一个ASCII字符来进行区分
0bit—7bit:真正的命令编号 0—255每一组共计支持256个
30-6:IOCTL代码编写:
1) 代码的功能设计:
ALLON à 开全部灯
ALLOFF à 关全部灯
LEDON à 开指定的某个灯
LEDOFF à 关指定的某个灯
LEDREAD à 读全部灯的状态
TRANSFERà 先写入灯状态再向用户空间传递数据
2) 代码请参考视频
30-6:内核提供的制作IOCTL命令的工具
#define _IO(type,nr) //制作没有数据传输的命令
#define _IOR(type,nr,size) //制作读取数据的命令
#define _IOW(type,nr,size) //制作写入数据的命令
#define _IOWR(type,nr,size) //制作先写入后读取的双向传输命令
参数1:魔数àASCII字符
参数2:命令编号
参数3:要传递的数据的大小,此处不能填入数字,要填定义类型
关于定义类型:charà一个字节 shortà两个字节 intà四个字节
传递非标准定义的数据长度使用结构体类型,不考虑结构体内部数据对齐,其实这样做是为了你传递数据的方便
30-7:内核提供的分离IOCTL命令的工具
#define _IOC_DIR(nr) //分离读写控制
#define _IOC_TYPE(nr) //分离魔数
#define _IOC_NR(nr) //分离命令
#define _IOC_SIZE(nr) //分离数据长度
合作微信xydf321456