深入理解ioctl

简介:

《Linux设备驱动程序》ioctl详解

 


除了读取和写入设备之外,大部分驱动程序还需要通过设备驱动程序实行各种类型的硬件控制。简单的数据传输之外,大部分设备还可以执行其他一些操作,比如,用户空间经常会请求设备锁门,弹出介质,报告错误信息,改变波特率或者执行子破坏,等等。这些操作通常通过ioctl方法来支持。

 

ioctl在用户空间的原型:

 

int  ioctl(int fd, unsigned long  cmd, ...)

 

这里的...代表可变参数,他并不是代表任意数量的一组可变参数,通常,更具cmd来定,如果cmd不需要参数,那么...就不会被使用,如果cmd需要参数,则就会使用...所以,它只是代表一个可变参数。习惯上使用 char  *argp来定义。这里使用...就是为了编译时防止编译器进行类型检查。

 

ioctl命令


每个驱动,都会有自己的ictol命令,那么在不同的驱动,不同类型设备的驱动之间,这些命令必须唯一标示出来,例如,我们对非串口设备使用设置波特率的命令,如果按照通常意义上将,对ioctl命令从0或者1开始编号,假设1在串口驱动中代表设置波特率,由于其他原因,我们错误的在非串口设备中使用1的时候,可能并没有发生错误,只是进行了其他的操作而已,那么这是在驱动程序中不允许的。但是如果ioctl命令编号是唯一的,那么就不会出现这种无意间成功的完成了意想不到的操作。

 

为了方便程序员唯一的创建ioctl命令编号,内核中作了如下规定:

每一个命令号被分为多个字段。新的内核(2.6)中,定义号码的新方法中使用4个字段来唯一标示一个命令。

 

<linux/ioctl.h>中对个字段的位数做出了定义

 

 

type

         幻数。选择一个号码,并在整个驱动程序中使用这个号码。

 

number

         序数

 

direction

         传输方向。_IOC_NONE(没有数据传输),_IOC_READ,_IOC_WRITE以及_IOC_READ|_IOC_WRITE(双向)这些方向。传输方向是站在应用程序的角度来看的。如果应用程序需要从驱动中读取数据,则方向应该是_IOC_READ。

 

size

      所涉及的用户数据大小。对于大量数据传输可以忽略该字段。

 

以下是<linux/ioctl.h>中对各个字段所占的位数做出了说明

 

#define _IOC_NRBITS     8       //序数占8位
#define _IOC_TYPEBITS   8     //幻数占8位

/*
 * Let any architecture override either of the following before
 * including this file.
 */

#ifndef _IOC_SIZEBITS         //size字段
# define _IOC_SIZEBITS  14 
#endif

#ifndef _IOC_DIRBITS
# define _IOC_DIRBITS   2    //direction 字段
#endif

 

对于自己的驱动,如果需要使用特定的ioctl命令,则必须创建ioctl命令以及编号。内核中给出了创建ioctl命令的宏

 

/* used to create numbers */
#define _IO(type,nr)            _IOC(_IOC_NONE,(type),(nr),0)
#define _IOR(type,nr,size)      _IOC(_IOC_READ,(type),(nr),(_IOC_TYPECHECK(size)))
#define _IOW(type,nr,size)      _IOC(_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
#define _IOWR(type,nr,size)     _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
#define _IOR_BAD(type,nr,size)  _IOC(_IOC_READ,(type),(nr),sizeof(size))
#define _IOW_BAD(type,nr,size)  _IOC(_IOC_WRITE,(type),(nr),sizeof(size))
#define _IOWR_BAD(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))

 

 

 


版权申明:
转载文章请注明原文出处http://blog.csdn.net/feiyinzilgd/archive/2010/03/03/5341173.aspx
并请联系谭海燕本人或者前往谭海燕个人主页留言

目录
相关文章
hi3531的pcie atu资源重映射
<p>1. 设置ATU 区域号寄存器为需要配置的地址转换区编号。<br> 2. 设置ATU Region Lower Base Address Register 和ATU Region Upper Base Address<br> Register。(在此区域内的目标地址将由区域号寄存器所在的ATU 转换)<br> 3. 设置ATU Region Limit Address Regi
2881 0
|
NoSQL Redis
基于Redis的高可用分布式锁——RedLock
这篇文章介绍了基于Redis的高可用分布式锁RedLock的概念、工作流程、获取和释放锁的方法,以及RedLock相比单机锁在高可用性上的优势,同时指出了其在某些特殊场景下的不足,并提到了ZooKeeper作为另一种实现分布式锁的方案。
418 2
基于Redis的高可用分布式锁——RedLock
|
7月前
|
机器学习/深度学习 缓存 负载均衡
Qwen MoE关键细节:通过全局负载均衡提升模型性能和专家的特异化程度
Qwen MoE关键细节:通过全局负载均衡提升模型性能和专家的特异化程度
|
10月前
|
存储 安全 Java
系统安全架构的深度解析与实践:Java代码实现
【11月更文挑战第1天】系统安全架构是保护信息系统免受各种威胁和攻击的关键。作为系统架构师,设计一套完善的系统安全架构不仅需要对各种安全威胁有深入理解,还需要熟练掌握各种安全技术和工具。
453 10
|
JavaScript
NodeJs——无法使用内网IP访问
NodeJs——无法使用内网IP访问
150 1
|
SQL JavaScript 分布式数据库
使用Vue+ ECharts进行动态图表展示
Vue是一个用于构建用户界面的渐进式JavaScript框架,可以轻松构建单页面应用程序(SPA)。ECharts是一个基于JavaScript的数据可视化库,可以通过简单的配置实现各种图表的展示和交互。
826 0
|
Ubuntu 物联网 Linux
手把手移植物联网项目到arm开发板笔记(上)
手把手移植物联网项目到arm开发板笔记
651 0
|
消息中间件 算法 物联网
RT-Thread快速入门-初探RT-Thread
RT-Thread快速入门-初探RT-Thread
431 0