`
bigfirebird
  • 浏览: 128894 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

高级IO操作——ioctl

阅读更多
_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() 的实现,其它的类似。

在 asm-generic/ioctl.h 里可以看到 _IO() 的定义:
#define _IO(type,nr)        _IOC(_IOC_NONE,(type),(nr),0)
再看 _IOC() 的定义:
#define _IOC(dir,type,nr,size) \
    (((dir)  << _IOC_DIRSHIFT) | \
     ((type) << _IOC_TYPESHIFT) | \
     ((nr)   << _IOC_NRSHIFT) | \
     ((size) << _IOC_SIZESHIFT))
可 见,_IO() 的最后结果由 _IOC() 中的 4 个参数移位组合而成。

再看 _IOC_DIRSHIT 的定义:
#define _IOC_DIRSHIFT    (_IOC_SIZESHIFT+_IOC_SIZEBITS)
_IOC_SIZESHIFT 的定义:
#define _IOC_SIZESHIFT    (_IOC_TYPESHIFT+_IOC_TYPEBITS)
_IOC_TYPESHIF 的定义:
#define _IOC_TYPESHIFT    (_IOC_NRSHIFT+_IOC_NRBITS)
_IOC_NRSHIFT 的定义:
#define _IOC_NRSHIFT    0
_IOC_NRBITS 的定义:
#define _IOC_NRBITS    8
_IOC_TYPEBITS 的定义:
#define _IOC_TYPEBITS    8
由 上面的定义,往上推得到:
引 用
_IOC_TYPESHIFT = 8

_IOC_SIZESHIFT = 16

_IOC_DIRSHIFT = 30


所以,(dir)  << _IOC_DIRSHIFT) 表是 dir 往左移 30 位,即移到 bit31~bit30 两位上,得到方向(读写)的属性;
(size) << _IOC_SIZESHIFT) 位左移 16 位得到“数据大小”区;
(type) << _IOC_TYPESHIFT) 左 移 8位得到"魔数区" ;
(nr)   << _IOC_NRSHIFT)      左移 0 位( bit7~bit0) 。

这样,就得到了 _IO() 的宏值。



beyes 2009-09-26 11:23
这几个宏的使用格式为:
_IO (魔数, 基数);
_IOR (魔数, 基数, 变量型)
_IOW  (魔数, 基数, 变量型)
_IOWR (魔数, 基数,变量型 )
魔数 (magic number)
魔数范围为 0~255 。通常,用英文字符 "A" ~ "Z" 或者 "a" ~ "z" 来表示。设备驱动程序从传递进来的命令获取魔数,然后与自身处理的魔数想比较,如果相同则处理,不同则不处理。魔数是拒绝误使用的初步辅助状态。设备驱动 程序可以通过 _IOC_TYPE (cmd) 来获取魔数。不同的设备驱动程序最好设置不同的魔数,但并不是要求绝对,也是可以使用其他设备驱动程序已用过的魔数。

基(序列号)数
基数用于区别各种命令。通常,从 0开始递增,相同设备驱动程序上可以重复使用该值。例如,读取和写入命令中使用了相同的基数,设备驱动程序也能分辨出来,原因在于设备驱动程序区分命令时 使用 switch ,且直接使用命令变量 cmd值。创建命令的宏生成的值由多个域组合而成,所以即使是相同的基数,也会判断为不同的命令。设备驱动程序想要从命令中获取该基数,就使用下面的宏:
_IOC_NR (cmd)
通常,switch 中的 case 值使用的是命令的本身。

变 量型
变量型使用 arg 变量指定传送的数据大小,但是不直接代入输入,而是代入变量或者是变量的类型,原因是在使用宏创建命令,已经包含了 sizeof() 编译命令。比如 _IOR() 宏的定义是:
引用
#define _IOR(type,nr,size)    _IOC(_IOC_READ,(type),(nr),(_IOC_TYPECHECK(size)))

而 _IOC_TYPECHECK() 的定义正是:
引用
#define _IOC_TYPECHECK(t) (sizeof(t))


设 备驱动程序想要从传送的命令获取相应的值,就要使用下列宏函数:
_IOC_SIZE(cmd)


_IO 宏
该宏函数没有可传送的变量,只是用于传送命令。例如如下约定:
引用
#define TEST_DRV_RESET _IO ('Q', 0)

此时,省略由应用程序传送的 arg 变量或者代入 0 。在应用程序中使用该宏时,比如:

ioctl (dev, TEST_DEV_RESET, 0)   或者  ioctl (dev, TEST_DRV_RESET) 。

这是因为变量的有效因素是可变因素。只作为命令使用时,没有必要判 断出设备上数据的输出或输入。因此,设备驱动程序没有必要执行设备文件大开选项的相关处理。

_IOR 宏
该函数用 于创建从设备读取数据的命令,例如可如下约定:
引用
#define TEST_DEV_READ  _IRQ('Q', 1, int)

这 说明应用程序从设备读取数据的大小为 int 。下面宏用于判断传送到设备驱动程序的 cmd 命令的读写状态:
_IOC_DIR (cmd)

运行该宏时,返回值的类型 如下:
_IOC_NONE                             :  无属性
_IOC_READ                             :  可读属性
_IOC_WRITE                           : 可写属性
_IOC_READ | _IOC_WRITE : 可读,可写属性
使用该命令时,应用程序的 ioctl() 的 arg 变量值指定设备驱动程序上读取数据时的缓存(结构体)地址。

_IOW 宏
用于创建设 备上写入数据的命令,其余内容与 _IOR 相同。通常,使用该命令时,ioctl() 的 arg 变量值指定设备驱动程序上写入数据时的缓存(结构体)地址。

_IOWR 宏
用于创建设备上读写数据的命令。其余内 容与 _IOR 相同。通常,使用该命令时,ioctl() 的 arg 变量值指定设备驱动程序上写入或读取数据时的缓存 (结构体) 地址。

_IOR() , _IOW(), IORW() 的定义:
#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)))
分享到:
评论

相关推荐

    ioctl-sample.zip_io driver_ioctl_ioctl kb m_过滤驱动_过滤驱动程序

    在示例代码中,它可能展示了如何定义和使用特定于键盘和鼠标设备的ioctl命令,以实现对这些输入设备的高级控制。 最后,“过滤驱动程序”是在硬件设备驱动之上增加的一层软件。它的主要作用是在数据传输过程中插入...

    linux设备驱动归纳总结(三):4.ioctl的实现

    本篇文章将深入探讨Linux设备驱动中的一个重要特性——ioctl接口的实现,这是设备驱动程序与用户空间进行复杂交互的主要手段。 ioctl(Input/Output Control)是一种特殊的I/O控制命令,允许用户空间程序对设备进行...

    sgio:使用SG_IO ioctl的SCSI命令的golang库

    Sgio golang库,用于通过SG_IO ioctl发出SCSI命令 有关使用SG_IO的示例函数,请参见TestUnitReady() 例子: f, err := OpenScsiDevice("/dev/sg0")if err != nil {log.Fatalln(err)}defer f.Close()为SCSI命令填写...

    Linux中ioctl操作

    在深入探讨Linux中ioctl操作与网络相关功能之前,我们先简要回顾一下ioctl的基本概念。ioctl,即输入输出控制(Input/Output Control),是Linux和其他类Unix操作系统中用于执行设备特殊功能的一种系统调用。其主要...

    APUE(UNIX环境高级编程)——文件I/O篇

    内核通过文件描述符管理和文件状态保持一致性,例如`lseek`用于更改读写位置,`fcntl`和`ioctl`函数则提供了更复杂的文件控制功能。 【总结】 UNIX环境中的文件I/O是通过系统调用进行的,以文件描述符作为关键标识...

    Linux设备驱动程序学习(4)-高级字符驱动程序操作[(1)ioctl and llseek] - Linux设备驱动程序

    本文将深入探讨Linux设备驱动程序中的两个关键操作:ioctl和llseek,这两个操作是高级字符驱动程序的重要组成部分。 ioctl(Input/Output Control)函数是Linux系统中用于设备控制的一种方法,它允许应用程序向设备...

    Linux文件的IO操作

    Linux操作系统是现代计算平台中非常重要的一个组成部分,它支持广泛的IO操作,这些操作是操作系统管理文件和设备资源的基础。在Linux环境下,文件IO操作通常包括创建文件、读取文件、写入文件以及关闭文件等基本操作...

    ioctl系统调用流程

    Ioctl系统调用流程是Linux操作系统中的一种系统调用机制,用于控制设备文件的行为。该机制通过系统调用函数sys_ioctl来实现,下面将详细介绍ioctl系统调用流程。 一、系统调用框架 在Linux操作系统中,每个系统...

    linux3.16驱动unlocked_ioctl

    `ioctl`函数允许应用程序执行设备特定的操作,如配置硬件、获取状态信息等,这些操作通常是不能通过常规的读写操作完成的。`ioctl`调用由`ioctl`系统调用触发,参数包括文件描述符、命令代码和传递数据的指针。 2....

    ioctl函数的使用

    ioctl函数的使用 Ioctl函数是一种控制I/O设备的函数,主要用来控制设备的行为和交互。...ioctl函数是控制I/O设备的重要函数,通过使用ioctl函数,可以控制设备的行为和交互,并实现数据传输等操作。

    详细介绍哦ioctl函数用法, 一看必然会用。。。。

    ioctl 函数可以用来执行各种设备操作,如获取或设置设备参数、执行设备命令等。 在 Linux 系统中,ioctl 函数的使用非常广泛,如在网络编程中获取或设置网络接口的参数,在磁盘编程中获取或设置磁盘参数等。 ioctl...

    ioctl函数详解

    在Linux内核中,`ioctl`函数的实现依赖于文件操作结构体`file_operations`中的`unlocked_ioctl`或`compat_ioctl`成员函数。当用户空间调用`ioctl`时,系统会找到对应的设备驱动,并调用其中定义的`ioctl`处理函数。 ...

    ioctl 函数的用法打包

    #define MY_IOCTL_CMD _IO('M', 1) // 如果不需要参数 #define MY_IOCTL_CMD_WITH_ARG _IOW('M', 2, int) // 如果需要一个整型参数 ``` 这里,'M'是一个设备特定的类型字符,1和2是命令编号。 ### 3. 用户空间中的...

    IOCTL_CODE 计算器

    在Windows操作系统中,IOCTL(Input/Output Control)代码是一种用于设备驱动程序的特殊命令,它们允许用户模式的应用程序对设备进行低级别的控制操作。IOCTL_CODE计算器是开发者用来方便地创建和解析这些代码的工具...

    linux系统ioctl使用示例

    在 Linux 系统中,ioctl(Input/Output Control)是一种系统调用,用于控制和管理设备文件的输入/输出操作。ioctl 函数可以用来设置或获取设备文件的属性、控制设备的行为、执行特殊的 I/O 操作等。 在以下四个示例...

    i2c_ioctl详解

    3. **实现ioctl函数**:编写实现`ioctl`命令的函数,该函数需要处理不同的ioctl命令,并根据命令的不同执行相应的操作。 4. **用户空间调用ioctl**:应用程序可以通过调用`ioctl`函数来发送特定的ioctl命令到内核...

    ioctl函数.pdf

    根据 request 的类型,可以将 ioctl 请求分为六类:套接口操作、文件操作、接口操作、ARP 高速缓存操作、路由表操作和流系统操作。 套接口操作 套接口操作的 ioctl 请求有三个,它们都要求 ioctl 的第三个参数是...

    ioctl_example.zip

    总结来说,`ioctl_example.zip`提供的示例代码展示了如何在Linux设备驱动中使用`ioctl`进行设备控制,特别是针对LED设备的亮灭操作。通过对这个例子的学习,开发者可以更好地理解和实践`ioctl`在设备驱动中的应用。

    IOCTL_Test.rar_IOCTL__USB 驱动开发 3.2_ioctl_ioctl u_usb ioctl

    "ioctl_ioctl"可能是表示对IOCTL操作的进一步细化,而"u_usb ioctl"可能是指与USB设备相关的特定控制操作。在实际开发中,这可能涉及到创建自定义的IOCTL命令来控制USB设备的特殊功能,如配置设备、读取传感器数据等...

    ioctl_example.rar_ioctl_ioctl example_mdoc

    这对于编写设备驱动程序、操作系统内核编程以及嵌入式系统开发等高级主题是必不可少的知识。 总结来说,`ioctl_example`是一个用于学习`ioctl`调用和设备驱动编程的实例,它包含了驱动注册、`ioctl`命令处理和用户...

Global site tag (gtag.js) - Google Analytics