深入理解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
并请联系谭海燕本人或者前往谭海燕个人主页留言

目录
相关文章
|
3月前
看看FIQ和IRQ
看看FIQ和IRQ
38 0
|
5月前
|
存储 Unix Linux
关于epoll和mmap的思考
epoll 是 Linux 操作系统提供的一种 I/O 多路复用机制,用于监视多个文件描述符(通常是套接字、管道或文件),并在其中的某个文件描述符准备好读或写时通知应用程序。它是一种高效的事件通知机制,特别适用于高性能的网络应用程序,如 Web 服务器和代理服务器。
|
9月前
|
存储 缓存 流计算
uvc驱动ioctl分析上
uvc驱动ioctl分析上
86 0
|
9月前
|
存储 缓存 索引
uvc驱动ioctl分析下
uvc驱动ioctl分析下
135 0
|
网络协议 Linux 缓存
struct s_mbuf与struct sk_buff
struct s_mbuf与struct sk_buff本文的copyleft归gfree.wind@gmail.com所有,使用GPL发布,可以自由拷贝,转载。但转载请保持文档的完整性,注明原作者及原链接,严禁用于任何商业用途。
1284 0
|
机器学习/深度学习 Linux 程序员
|
机器学习/深度学习 监控
|
监控 网络协议
printk一些技巧【转】
转自:http://haohetao.iteye.com/blog/1147791 转自:http://blog.csdn.net/wbd880419/article/details/73530550 内核通过 printk() 输出的信息具有日志级别,日志级别是通过在 printk() 输出的字符串前加一个带尖括号的整数来控制的,如 printk("Hello, world!/n");。
1340 0