测试程序 ioctl , 不同版本下的ioctl存在区别
inux-2.6.36之前的内核:
- int (*ioctl)(struct inode *inode,struct file *filp,unsigned int cmd,unsigned long arg)
- (1)inode和file:ioctl的操作有可能是要修改文件的属性,或者访问硬件。要修改
- 文件属性的话,就要用到这两个结构体了,所以这里传来了它们的指针;
- (2)cmd:从用户空间传下来的命令参数;
- (3)arg:可选参数,主要用于定义应用层和驱动层进行命令调用时候是否涉及数据读写;</span></span>
- int (*ioctl)(struct file *filp,unsigned int cmd,unsigned long arg)
- (1)file:ioctl的操作有可能是要修改文件的属性,或者访问硬件。要修改
- 文件属性的话,就要用到这两个结构体了,所以这里传来了它们的指针;
- (2)cmd:从用户空间传下来的命令参数;
- (3)arg:可选参数,主要用于定义应用层和驱动层进行命令调用时候是否涉及数据读写;</span>
3 再论Linux内核ioctl函数
3.1 什么是ioctl?
ioctl是设备驱动程序中对设备的I/O通道进行管理的函数。所谓对I/O通道进行管理,就是对设备的一些特性进行控制,例如串口的传输波特率、马达的转速等等。它的调用个数如下:
int ioctl(int fd, ind cmd, …);
其中fd就是用户程序打开设备时使用open函数返回的文件标示符,cmd就是用户程序对设备的控制命令,至于后面的省略号,那是一些补充参数,一般最多一个,有或没有是和cmd的意义相关的。ioctl函数是文件结构中的一个属性分量,就是说如果你的驱动程序提供了对ioctl的支持,用户就可以在用户程序中使用ioctl函数控制设备的I/O通道。
int ioctl(int fd, ind cmd, …);
其中fd就是用户程序打开设备时使用open函数返回的文件标示符,cmd就是用户程序对设备的控制命令,至于后面的省略号,那是一些补充参数,一般最多一个,有或没有是和cmd的意义相关的。ioctl函数是文件结构中的一个属性分量,就是说如果你的驱动程序提供了对ioctl的支持,用户就可以在用户程序中使用ioctl函数控制设备的I/O通道。
3.2 ioctl实现原理
在驱动当中实现的ioctl函数中,其实就是一个switch case的结构,每一个case对应一个命令码,对应一些命令操作。如何实现这些操作是软件工程师根据程序开发的需求来定制,因为每一个设备都是特定的,关键在于如何组织命令码,因为在ioctl中命令码是唯一联系用户程序命令和驱动程序的路径。
在Linux内核中是这样定义一个命令码的:
| 设备类型 | 序列号 | 方向 | 数据尺寸 |
|----------|--------|------|----------|
| 8bit | 8bit | 2bit | 2~14bit |
|----------|--------|------|----------|
其实,在Linux内核中,命令就是一个整数形式的命令码。可是这样复杂的命令码看起来不够直观,开发人员很难记住,为此,Linux内核专门为这些命令码提供了一些宏,这些宏可以根据便于理解的字符串生成命令码,或者是从,命令码中得到一些用户可以理解的字符串用来标明相应设备的设备类型、设备序列号、数据传输方向、数据传输尺寸。
3.2.1 Linux内核ioctl命令宏定义详解
在设备驱动开发中,应用层和驱动层进行命令交互和数据传输过程中无非这四种情况:
1.无任何参数的命令控制;
2.应用层从驱动中读取数据;
3.应用层写数据到驱动层;
4.应用层和驱动层进行双向的命令交互;
在Linux内核中定义了以下宏用来定义命令码:
- //nr为序号,datatype为数据类型,如int
- _IO(type, nr ) //没有参数的命令
- _IOR(type, nr, datatype) //从驱动中读数据
- _IOW(type, nr, datatype) //写数据到驱动
- _IOWR(type,nr, datatype) //双向传送</span>
- #define DISP_IOC_MAGIC 'disp' //定义类型
- #define DISP_IOCSET _IOW(DISP_IOC_MAGIC,0,int)
- #define DISP_IOCGQSET _IOR(DISP_IOC_MAGIC, 1, int)
3.2.2 ioctl函数命令实现
实现ioctl函数包含以下三个技术环节:
(1) 返回值:
ioctl函数根据应用层传入的相应命令到驱动层的ioctl去匹配相应的命令,命令的执行在一个switch语句中,如果命令不匹配,通常返回一个-ENVAL值;
(2) 参数使用:
用户使用 int ioctl(int fd,unsigned long cmd,....)时候传递参数;
驱动层调用 int (*ioctl)(struct inode *inode,struct file *filp,unsigned int cmd,unsigned long arg)中的arg参数进行与应用层的参数传递,如果arg是一个整数,可以直接使用,如果是一个指针,则要判断指针的地址的合法性,因此使用之前需要进行正确的检查。不需要检查的是:
- copy_from_user
- copy_to_user
- get_user
- put_user
- _get_user
- __put_user
- static int xxx_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
- {
- switch (cmd)
- {
- case XXX_IOCTL_CMD_1:
- {
- //to do
- }
- break;
- case XXX_IOCTL_CMD_2:
- {
- //to do
- }
- break;
- default:
- break;
- }
- } </span>
posted on 2016-11-09 14:47 Red_Point 阅读(1578) 评论(0) 编辑 收藏 举报
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步