18、ioctl接口
unlocked_ioctrl 接口
1、什么是unlocked_ioctrl 接口?
unlocked_ioctrl 在之前的名字是ioctrl, 之前的是带锁的,现在的是不带锁的, 原因是为了提高实时性
虽然名字发生了改变,但是功能和对应的系统调用均没有发生变化
2、unlocked_ioctl 和 read/write 有什么相同点和不同点?
1、相同点
都可以往内核写数据
2、不同点
read函数只能完成读的功能, write 只能完成写的功能
读取大量数据的时候效率高
ioctl 即可以读也可以写 读取大量数据的效率低
3、unlocked_ioctrl 接口命令规则。
命令一个unsigned int 类型的无符号整型数
魔数 (magic number)
魔数范围为 0~255 。通常,用英文字符 “A” ~ “Z” 或者 “a” ~ “z” 来表示。设备驱动程序从传递进来的命令获取魔数,然后与自身处理的魔数想比较,如果相同则处理,不同则不处理。魔数是拒绝误使用的初步辅助状态。设备驱动 程序可以通过 _IOC_TYPE (cmd) 来获取魔数。不同的设备驱动程序最好设置不同的魔数,但并不是要求绝对,也是可以使用其他设备驱动程序已用过的魔数。
基(序列号)数
基数用于区别各种命令。通常,从 0开始递增,相同设备驱动程序上可以重复使用该值。例如,读取和写入命令中使用了相同的基数,设备驱动程序也能分辨出来,原因在于设备驱动程序区分命令时 使用 switch ,且直接使用命令变量 cmd值。创建命令的宏生成的值由多个域组合而成,所以即使是相同的基数,也会判断为不同的命令。设备驱动程序想要从命令中获取该基数,就使用下面的宏:
_IOC_NR (cmd)
通常,switch 中的 case 值使用的是命令的本身。
变量型
变量型使用 arg 变量指定传送的数据大小,但是不直接代入输入,而是代入变量或者是变量的类型,原因是在使用宏创建命令,已经包含了 sizeof() 编译命令
第一个分区 : 0-7位 , 命令的编号 0-255
第二个分区: 8-15位, 命令的幻(魔)数
第一个分区和第二个分区, 主要是用来区分命令的
第三个分区:16-29 表示传递的数据大小
第四个分区:30-31 代表读写方向
参数 | 功能 |
---|---|
00 | 表示应用程序和驱动程序没有数据传递 |
10 | 表示应用程序从驱动里面读数据 |
01 | 表示应用程序向驱动里面写数据 |
11 | 表示应用程序先写数据到驱动,然后再从驱动里面读数据 |
4、命令的合成与分解宏
1、合成宏:
宏定义 | 功能 |
---|---|
_IO(type, nr) | 用来定义没有数据传递的命令 |
_IOR(type, nr, size) | 用来定义从驱动中读取数据的命令 |
_IOW(type, nr, size) | 用来定义向驱动写入数据的命令 |
_IOWR(type, nr, size) | 用来定义数据交换类型的命令**,先写入,在读取** |
参数 | 描述 |
---|---|
type | 表示命令组成的幻(魔)数,也就是8-15位 |
nr | 表示命令组成的编号,也就是0-7位 |
size | 表示命令组成的参数传递大小,注意这里不是传递数字,而是数据类型, 如要传递4字节,就可以写成int |
#ifndef _IOC_NONE
# define _IOC_NONE 0U //0x00
#endif
#ifndef _IOC_WRITE
# define _IOC_WRITE 1U //0x01
#endif
#ifndef _IOC_READ
# define _IOC_READ 2U //0x10
#endif
#define _IOC(dir,type,nr,size) \
(((dir) << _IOC_DIRSHIFT) | \ // dir << 30
((type) << _IOC_TYPESHIFT) | \ // type << 8
((nr) << _IOC_NRSHIFT) | \ //nr << 0
((size) << _IOC_SIZESHIFT)) //size << 16
#define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0)
#define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size)
#define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),sizeof(size))
#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
2、分解宏
宏定义 | 功能 |
---|---|
_IOC_DIR(nr) | 分解命令的方向,也就是 30-31 位的值 |
_IOC_TYPE(nr) | 分解命令的魔数,也就是上面的8-15位的值 |
_IOC_NR(nr) | 分解命令的编号,也就是上面的0-7位的值 |
_IOC_SIZE(nr) | 分解命令的数据大小,也就是上面的16-29位 |
参数说名 nr 要分解的命令
#define _IOC_DIR(nr) (((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
//(nr>>30)& 0x3
#define _IOC_TYPE(nr) (((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK)
//(nr>>8)& 0xFF
#define _IOC_NR(nr) (((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK)
// (nr)&0xFF
#define _IOC_SIZE(nr) (((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK)
//(nr>>16)&0x3FFF
应用层的ioctl与驱动的ioctrl的参数对应关系