3.7 ioctl函数中case的详细分析
2019-07-12 13:47发布
生成海报
在分析应用程序的ioctl调用的时候,内核中将这些ioctl的调用信息打印出来,但是打印的是unsignedint类型的16进制值,这样,如果想要分析这些ioctl调用的话,就需要将这些ioctl调用的16进制值计算出来。每一个ioctl调用都有如下的形式:
intioctl(int fd, int cmd, …);
可以看出来,这个cmd是int类型的,它里面包含一定的信息,下面就来分析这个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_capability,size就是表示这个结构体的大小。
dir代表_IOC_NONE,_IOC_WRITE和_IOC_READ中的一种或_IOC_WRITE和_IOC_READ的组合。其中_IOC_NONE=
0U, _IOC_WRITE = 1U,_IOC_READ= 2U;这三个值只需要2位就可以表示了。
至此,应该就理解这里面的宏的含义了,但是对于打印出来的值,需要没一个都计算出来么,显然不用,这个32位数的最后8位是nr,代表的是序号,8~16位是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
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮