Chinaunix首页 | 论坛 | 博客
  • 博客访问: 383141
  • 博文数量: 48
  • 博客积分: 743
  • 博客等级: 上士
  • 技术积分: 956
  • 用 户 组: 普通用户
  • 注册时间: 2011-11-22 13:51
文章分类

全部博文(48)

文章存档

2015年(3)

2014年(17)

2012年(23)

2011年(5)

分类: 嵌入式

2014-03-14 13:45:08

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

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

点击(此处)折叠或打开

  1. #define _IOC_DIRBITS  2 //方向(direction)字段的字位宽度,2bits
  2. #define _IOC_TYPEBITS 8  //幻数(type)字段的字位宽度,8bits
  3. #define _IOC_NRBITS   8   //序数(number)字段的字位宽度,8bits
  4. #define _IOC_SIZEBITS 14 //大小(size)字段的字位宽度,14bits

  5. #define _IOC_NONE     0U  //没有数据传输
  6. #define _IOC_WRITE    1U  //向设备写入数据,驱动程序必须从用户空间读入数据
  7. #define _IOC_READ     2U  //从设备中读取数据,驱动程序必须向用户空间写入数据

  8. #define _IOC_NRMASK     ((1 << _IOC_NRBITS)-1)       //序数字段的掩码,0x000000FF
  9. #define _IOC_TYPEMASK  ((1 << _IOC_TYPEBITS)-1)    //幻数字段的掩码,0x000000FF
  10. #define _IOC_SIZEMASK   ((1 << _IOC_SIZEBITS)-1)   //大小字段的掩码,0x00003FFF
  11. #define _IOC_DIRMASK    ((1 << _IOC_DIRBITS)-1)     //方向字段的掩码,0x00000003

  12. #define _IOC_NRSHIFT    0                                 //序数字段在整个字段中的位移,0
  13. #define _IOC_TYPESHIFT  (_IOC_NRSHIFT+_IOC_NRBITS)        //幻数字段的位移,8
  14. #define _IOC_SIZESHIFT  (_IOC_TYPESHIFT+_IOC_TYPEBITS)    //大小字段的位移,16
  15. #define _IOC_DIRSHIFT   (_IOC_SIZESHIFT+_IOC_SIZEBITS)    //方向字段的位移,30

  16. #define _IOC(dir,type,nr,size) \
  17.    (((dir) << _IOC_DIRSHIFT) | \
  18.    ((type) << _IOC_TYPESHIFT) | \
  19.    ((nr) << _IOC_NRSHIFT) | \
  20.    ((size) << _IOC_SIZESHIFT))
  21. /* 生成cmd */
  22. #define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0) //构造无参数的命令编号
  23. #define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size))  //构造从驱动程序中读取数据的命令编号
  24. #define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),sizeof(size)) //用于向驱动程序写入数据命令
  25. #define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size)//用于双向传输
  26. /*从命令参数中解析数据*/
  27. #define _IOC_DIR(cmd)   (((cmd) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)   //从命令参数中解析出数据方向,即写进还是读出
  28. #define _IOC_TYPE(cmd)  (((cmd) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK) //从命令参数中解析出幻数type
  29. #define _IOC_NR(cmd)    (((cmd) >> _IOC_NRSHIFT) & _IOC_cmdMASK)    //从命令参数中解析出序数number
  30. #define _IOC_SIZE(cmd)  (((cmd) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK) //从命令参数中解析出用户数据大小
_IOC 宏将dirtypenrsize四个参数组合成一个cmd参数,如下图:


阅读(1346) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~