关于ioctl幻数构造

      在编写ioctl 代码之前,需要选择对应不同命令的编号。为了防止对错误的设备使用正确的命 令,命令号应该在系统范围内唯一,这种错误匹配并不是不会发生,程序可能发现自己正在试图对 FIFO 和 audio 等 这类非串行设备输入流修改波特率,如果每一个 ioctl 命令都是唯一的,应用程序进行这种操作时就 会得到一个 EINVAL 错误,而不是无意间成功地完成了意想不到的操作。

     要 按 Linux 内核的约定方法为驱动程序选择 ioctl 编 号,应该首先看看 include/asm/ioctl.h (我在网上下载的是2.6.29内核,在asm下没用找到ioctl.h文件,相应的变换到了目录asm-generic下)和 Doucumention/ioctl-number.txt 这 两个文件。头文件定义了要使用的位字段:类型(幻数)、序数、传送方向以及参数大小等。 ioctl-number.txt 文 件中罗列了内核所使用的幻数,选择自己的幻数要避免和内核冲突。以下是对 include/asm/ioctl.h 中 定义的宏的注释:

#define          _IOC_NRBITS           8                   // 序数( number )字段的字位宽度, 8bits

#define          _IOC_TYPEBITS        8                     // 幻数( type )字段的字位宽度, 8bits

#define          _IOC_SIZEBITS         14                  // 大小( size )字段的字位宽度, 14bits

#define          _IOC_DIRBITS         2                    // 方向( direction )字段的字位宽 度, 2bits

 

#define          _IOC_NRMASK          ((1 << _IOC_NRBITS)-1)     // 序数字段的掩 码, 0x000000FF

#define          _IOC_TYPEMASK     ((1 << _IOC_TYPEBITS)-1)   // 幻数字段的掩 码, 0x000000FF

#define          _IOC_SIZEMASK       ((1 << _IOC_SIZEBITS)-1)    // 大小字段的掩 码, 0x00003FFF

#define          _IOC_DIRMASK        ((1 << _IOC_DIRBITS)-1)     // 方向字段的掩 码, 0x00000003

 

#define         _IOC_NRSHIFT         0                                                          // 序数字段在整个 字段中的位移, 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

 

/*

* Direction bits.

*/

#define  _IOC_NONE       0U      // 没有数据传输

#define  _IOC_WRITE     1U      // 向设备写入数 据,驱动程序必须从用户空间读入数据

#define  _IOC_READ       2U      // 从设备中读取数 据,驱动程序必须向用户空间写入数据

 

 

/*

*_IOC  宏将 dir  type  nr  size 四个参数组合成一个 cmd 参数,如下图:

*

*/

 500)this.width=500;" border=0>

 

#define  _IOC (dir ,type ,nr ,size ) /

        (((dir )   << _IOC_DIRSHIFT) | /

          ((type ) << _IOC_TYPESHIFT) | /

          ((nr )    << _IOC_NRSHIFT) | /

          ((size ) << _IOC_SIZESHIFT))

 

/*

* used to create numbers 

*/

// 构造无参数的命令编号

#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 ))

 

/* 

*used to decode ioctl numbers..

  */

// 从命令参数中解析出数据方向,即写进还是读出

#define  _IOC_DIR (nr )           (((nr ) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)

// 从命令参数中解析出幻数 type

#define  _IOC_TYPE (nr )               (((nr ) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK)

// 从命令参数中解析出序数 number

#define  _IOC_NR (nr )            (((nr ) >> _IOC_NRSHIFT) & _IOC_NRMASK)

// 从命令参数中解析出用户数据大小

#define  _IOC_SIZE (nr )          (((nr ) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK)

 

/* ...and for the drivers/sound files... */

 

#define  IOC_IN              (_IOC_WRITE << _IOC_DIRSHIFT)

#define  IOC_OUT           (_IOC_READ << _IOC_DIRSHIFT)

#define  IOC_INOUT       ((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT)

#define  IOCSIZE_MASK        (_IOC_SIZEMASK << _IOC_SIZESHIFT)

#define  IOCSIZE_SHIFT        (_IOC_SIZESHIFT)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值