ioctl函数

linux驱动程序开发中,ioctl命令编号问题,应该遵循include/asm/ioctl.h和Documentation/ioctl-number.txt这两个文件。一般命令使用四个字段来组成32位的值来编码:类型(幻数)、序数、传送方向以及参数大小。 Documentation/ioctl-number.txt已经罗列出了内核中使用的幻数,我们的驱动程序中应该避免与其冲突。

定义号码的四个字段如下所示:

type  幻数。选择一个号码,在整个程序中使用,该字段占8位。(_IOC_TYPEBITS)

number 序数。依次按顺序增长,也占8位。(_IOC_NRBITS)

direction。 数据的传输方向。这个方向是从用户的角度来看的,_IOC_NONE(没有数据传输),_IOC_READ(从驱动读出数据到用户)、_IOC_WRITE(从用户写数据到驱动)以及_IOC_READ|_IOC_WRITE(双向传输数据)。

size 所涉及的用户数据的大小。与具体的体系结构相关,通常占13位或14位。_IOC_SIZEBITS定义其具体位数。

文件中定义了一些常用的宏来构造命令编号。我们拿2.6.14版本来举例。其中我们需要的有如下几个宏定义,其他属于从已定义的命令中解析各个字段的值,我们暂不考虑。

/* 定义了每个字段的长度:*/

**************************************************

_IO, _IOR, _IOW, _IOWR 宏的用法与解析
在驱动程序里, ioctl() 函数上传送的变量 cmd 是应用程序用于区别设备驱动程序请求处理内容的值。cmd除了可区别数字外,还包含有助于处理的几种相应信息。 cmd的大小为 32位,共分 4 个域:

bit31~bit30 2位为 “区别读写” 区,作用是区分是读取命令还是写入命令。

bit29~bit15 14位为 "数据大小" 区,表示 ioctl() 中的 arg 变量传送的内存大小。

bit20~bit08  8位为 “魔数"(也称为"幻数")区,这个值用以与其它设备驱动程序的 ioctl 命令进行区别。

bit07~bit00   8位为 "区别序号" 区,是区分命令的命令顺序序号。

像 命令码中的 “区分读写区” 里的值可能是 _IOC_NONE (0值)表示无数据传输,_IOC_READ (读), _IOC_WRITE (写) , _IOC_READ|_IOC_WRITE (双向)。

内核定义了 _IO() , _IOR() , IOW() 和 _IOWR() 这 4 个宏来辅助生成上面的 cmd 。下面分析 _IO() 的实现,其它的类似。

*********************************************************************************************

*****************************************************8

#define _IOC_NRBITS    8
#define _IOC_TYPEBITS    8
#define _IOC_SIZEBITS    14
#define _IOC_DIRBITS    2

/*定义了每个字段在32位整数中的偏移量*/

#define _IOC_NRSHIFT    0
#define _IOC_TYPESHIFT    (_IOC_NRSHIFT+_IOC_NRBITS)
#define _IOC_SIZESHIFT    (_IOC_TYPESHIFT+_IOC_TYPEBITS)
#define _IOC_DIRSHIFT    (_IOC_SIZESHIFT+_IOC_SIZEBITS)

/*定义了数据传输方向,从用户角度来看 */
#define _IOC_NONE    0U
#define _IOC_WRITE    1U
#define _IOC_READ    2U

 

/*根据四个字段值生成一个命令编号,一般不直接使用*/

#define _IOC(dir,type,nr,size) /
    (((dir)  << _IOC_DIRSHIFT) | /
     ((type) << _IOC_TYPESHIFT) | /
     ((nr)   << _IOC_NRSHIFT) | /
     ((size) << _IOC_SIZESHIFT))

 

/* 真正的根据类型、序号、方向和大小四个参数生成命令编号的宏,根据具体情况选择以下四个之一*/
#define _IO(type,nr)       _IOC(_IOC_NONE,(type),(nr),0)                                /*不进行数据传输*/
#define _IOR(type,nr,size)   _IOC(_IOC_READ,(type),(nr),sizeof(size))             /*从驱动读取数据*/
#define _IOW(type,nr,size)    _IOC(_IOC_WRITE,(type),(nr),sizeof(size))          /*将用户数据写入到驱动*/
#define _IOWR(type,nr,size)   _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))        /*双向传输数据*/

使用例子:

使用k作为幻数:

#define MY_MAGIC_DATA 'k'

#define MY_IOC_PRINT_DATA  _IO(MY_MAGIC_DATA, 1)

#define MY_IOC_GET_DATA  _IOR(MY_MAGIC_DATA, 2, int)

#define MY_IOC_SET_DATA  _IOW(MY_MAGIC_DATA, 3, int)

#define MY_IOC_EXCHANGE_DATA _IOWR(MY_MAGIC_DATA,4,int)


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值