NXP

3.7 ioctl函数中case的详细分析

2019-07-12 13:47发布

在分析应用程序的ioctl调用的时候,内核中将这些ioctl的调用信息打印出来,但是打印的是unsignedint类型的16进制值,这样,如果想要分析这些ioctl调用的话,就需要将这些ioctl调用的16进制值计算出来。每一个ioctl调用都有如下的形式: intioctl(int fd, int cmd, …) 可以看出来,这个cmdint类型的,它里面包含一定的信息,下面就来分析这个cmd参数是怎么构造成的。 它们的定义在/include/uapi/linux/videodev2.h/include/uapi/asm-generic/ioctl.h中。
VIDIOC_QUERYCAP为例来分析: #define VIDIOC_QUERYCAP _IOR('V', 0, struct v4l2_capability) #define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),(_IOC_TYPECHECK(size))) #define _IOC(dir,type,nr,size) (((dir) << _IOC_DIRSHIFT) | ((type) << _IOC_TYPESHIFT) | ((nr) << _IOC_NRSHIFT) | ((size) << _IOC_SIZESHIFT)) #define _IOC_TYPECHECK(t) (sizeof(t)) # define _IOC_NONE 0U # define _IOC_WRITE 1U # define _IOC_READ 2U #define _IOC_NRSHIFT 0 #define _IOC_TYPESHIFT (_IOC_NRSHIFT+_IOC_NRBITS) // = 8 #define _IOC_SIZESHIFT (_IOC_TYPESHIFT+_IOC_TYPEBITS) // = 16 #define _IOC_DIRSHIFT (_IOC_SIZESHIFT+_IOC_SIZEBITS) // = 30 #define _IOC_NRBITS 8 #define _IOC_TYPEBITS 8 #define _IOC_SIZEBITS 14 #define _IOC_DIRBITS 2 可以看出来这个宏就是由几个值左移形成的,从这些宏中可以看出来,这32位的构成是这样的:
nr偏移为0,8位;type偏移为8,8位;size偏移为16,14位;dir偏移为30位,占2位。
从这些文件中大致可以了解到: nr应该就是number的缩写,它代表ioctl的序号。 type应该就是指ioctl的类型,它用一个大写字母表示,对于video类的应该就是用‘V’来表示了。 size代表cmd参数所对应的这个ioctl中第三个参数的类型大小,比如这个VIDIOC_QUERYCAP宏,通过这个ioctl调用,它会将查询到的capability保存在ioctl的第三个参数中,这个参数的类型就是structv4l2_capabilitysize就是表示这个结构体的大小。 dir代表_IOC_NONE_IOC_WRITE_IOC_READ中的一种或_IOC_WRITE_IOC_READ的组合。其中_IOC_NONE= 0U, _IOC_WRITE = 1U_IOC_READ= 2U;这三个值只需要2位就可以表示了。
至此,应该就理解这里面的宏的含义了,但是对于打印出来的值,需要没一个都计算出来么,显然不用,这个32位数的最后8位是nr,代表的是序号,816位是type类型,对于video类设备都是'V''V'ASCII码是86,转换成16进制就是0x56。同时每个宏的序号不同,根据这两点就可以找到对应的宏了。
比如在打印信息中: InMVC: mxc_v4l_do_ioctl c02c5651 <--> VIDIOC_DBG_G_CHIP_IDENT InMVC: mxc_v4l_do_ioctl c02c564a <--> VIDIOC_ENUM_FRAMESIZES InMVC: mxc_v4l_do_ioctl c0405602 <--> VIDIOC_ENUM_FMT