第六章:高级字符驱动程序操作
这章有以下几个部分主要内容:
1) 学习实现ioctl系统调用,它是用于设备控制的公共接口
2) 掌握如何使进程休眠(并唤醒)
3) poll/select
4) 异步通知
5) 定位设备
6) 设备文件的访问控制
以下为第1部分, ioctl的学习。
定义(摘自百度百科):
ioctl是设备驱动程序中对设备的I/O通道进行管理的函数。所谓对I/O通道进行管理,就
是对设备的一些特性进行控制,例如串口的传输波特率、马达的转速等等。他的调用个数
如下:
int ioctl(int fd, int cmd, …);
其中fd就是用户程式打开设备时使用open函数返回的文件标示符,cmd就是用户程式对设
备的控制命令,至于后面的省略号,那是一些补充参数,一般最多一个,有或没有是和
cmd的意义相关的。
ioctl函数是文件结构中的一个属性分量(就是在file_operations结构中),就是说如果你的驱动程式提供了对ioctl的支
持,用户就能在用户程式中使用ioctl函数控制设备的I/O通道。
实现操作(部分摘自百度百科):
在驱动程式中实现的ioctl函数体内,实际上是有一个switch{case}结构,每一个case对
应一个命令码,做出一些相应的操作。怎么实现这些操作,这是每一个程式员自己的事
情,因为设备都是特定的,这里也没法说。关键在于怎么样组织命令码,因为在ioctl中
命令码是唯一联系用户程式命令和驱动程式支持的途径。
命令码的组织是有一些讲究的,因为我们一定要做到命令和设备是一一对应的,这样才不
会将正确的命令发给错误的设备,或是把错误的命令发给正确的设备,或是把错误的
命令发给错误的设备。这些错误都会导致不可预料的事情发生,而当程式员发现了这些奇
怪的事情的时候,再来调试程式查找错误,那将是非常困难的事情。
所以在Linux核心中是这样定义一个命令码的:
____________________________________
| 设备类型 | 序列号 | 方向 |数据尺寸|
|----------|--------|------|--------|
| 8 bit | 8 bit |2 bit |8~14 bit|
|----------|--------|------|--------|
这样一来,一个命令就变成了一个整数形式的命令码。不过命令码非常的不直观,所以
Linux Kernel中提供了一些宏,这些宏可根据便于理解的字符串生成命令码,或是从
命令码得到一些用户能理解的字符串以标明这个命令对应的设备类型、设备序列号、数
据传送方向和数据传输尺寸。
我们就来看看这些宏吧:定义在include/asm-generic/ioctl.h中(我用的是2.6.32内核)
============================ioctl.h=================================
================================end of ioctl.h===============================
ioctl其实没有什么非常难的东西需要理解,关键是理解cmd命令码是怎么在用户程式里生成
并在驱动程式里解析的,程式员最主要的工作量在switch{case}结构中,因为对设备的
I/O控制都是通过这一部分的代码实现的。
先来看看scull.h中关于ioctl的definition