IOCTL

http://blog.chinaunix.net/uid-26993600-id-3253971.html

cmd拆分如下:

解释一下四部分,全部都在<asm-generic/ioctl.h>和ioctl-number.txt这两个文档有说明。

1)幻数:说得再好听的名字也只不过是个0~0xff的数,占8bit(_IOC_TYPEBITS)。这个数是用来区分不同的驱动的,像设备号申请的时候一样,内核有一个文档给出一些推荐的或者已经被使用的幻数。

/*Documentation/ioctl/ioctl-number.txt*/

164 'w' all CERN SCI driver

165 'y' 00-1F packet based user level communications

166 <mailto:[email protected]>

167 'z' 00-3F CAN bus card

168 <mailto:[email protected]>

169 'z' 40-7F CAN bus card

170 <mailto:[email protected]>

可以看到'x'是还没有人用的,我就拿这个当幻数!

2)序数:用这个数来给自己的命令编号,占8bit(_IOC_NRBITS),我的程序从1开始排序。

3)数据传输方向:占2bit(_IOC_DIRBITS)。如果涉及到要传参,内核要求描述一下传输的方向,传输的方向是以应用层的角度来描述的。

a)_IOC_NONE:值为0,无数据传输。

b)_IOC_READ:值为1,从设备驱动读取数据。

c)_IOC_WRITE:值为2,往设备驱动写入数据。

4d)_IOC_READ|_IOC_WRITE:双向数据传输。

4)数据大小:与体系结构相关,ARM下占14bit(_IOC_SIZEBITS),如果数据是int,内核给这个赋的值就是sizeof(int)。

既然内核这样定义cmd,就肯定有方法让用户方便定义:

_IO(type,nr) //没有参数的命令

_IOR(type,nr,size) //该命令是从驱动读取数据

_IOW(type,nr,size) //该命令是从驱动写入数据

_IOWR(type,nr,size) //双向数据传输

上面的命令已经定义了方向,我们要传的是幻数(type)、序号(nr)和大小(size)。在这里szie的参数只需要填参数的类型,如int,上面的命令就会帮你检测类型的正确然后赋值sizeof(int)。

有生成cmd的命令就必有拆分cmd的命令:

_IOC_DIR(cmd) //从命令中提取方向

_IOC_TYPE(cmd) //从命令中提取幻数

_IOC_NR(cmd) //从命令中提取序数

_IOC_SIZE(cmd) //从命令中提取数据大小

五、ioctl中的arg之整数传参。
应用层的ioctl的第三个参数是"...",这个跟printf的"..."可不一样,printf中是意味这你可以传任意个数的参数,而ioctl最多也只能传一个,"..."的意思是让内核不要检查这个参数的类型。也就是说,从用户层可以传入任何参数,只要你传入的个数是1.

一般会有两种的传参方法:

1)整数,那可是省力又省心,直接使用就可以了。

2)指针,通过指针的就传什么类型都可以了,当然用起来就比较烦。

results for ""

    No results matching ""