`
mintelong
  • 浏览: 392341 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Linux内核的ioctl函数学习

阅读更多
一、 什么是ioctl。
ioctl是设备驱动程序中对设备的I/O通道进行管理的函数。所谓对I/O通道进行管理,就
是对设备的一些特性进行控制,例如串口的传输波特率、马达的转速等等。它的调用个数
如下:
int ioctl(int fd, ind cmd, …);
其中fd就是用户程序打开设备时使用open函数返回的文件标示符,cmd就是用户程序对设
备的控制命令,至于后面的省略号,那是一些补充参数,一般最多一个,有或没有是和
cmd的意义相关的。
ioctl函数是文件结构中的一个属性分量,就是说如果你的驱动程序提供了对ioctl的支
持,用户就可以在用户程序中使用ioctl函数控制设备的I/O通道。

二、 ioctl的必要性
如果不用ioctl的话,也可以实现对设备I/O通道的控制,但那就是蛮拧了。例如,我们可
以在驱动程序中实现write的时候检查一下是否有特殊约定的数据流通过,如果有的话,
那么后面就跟着控制命令(一般在socket编程中常常这样做)。但是如果这样做的话,会
导致代码分工不明,程序结构混乱,程序员自己也会头昏眼花的。
所以,我们就使用ioctl来实现控制的功能。要记住,用户程序所作的只是通过命令码告
诉驱动程序它想做什么,至于怎么解释这些命令和怎么实现这些命令,这都是驱动程序要
做的事情。

三、 ioctl如何实现
这是一个很麻烦的问题,我是能省则省。要说清楚它,没有四五千字是不行的,所以我这
里是不可能把它说得非常清楚了,不过如果有读者对用户程序怎么和驱动程序联系起来感
兴趣的话,可以看我前一阵子写的《write的奥秘》。读者只要把write换成ioctl,就知
道用户程序的ioctl是怎么和驱动程序中的ioctl实现联系在一起的了。
我这里说一个大概思路,因为我觉得《Linux设备驱动程序》这本书已经说的非常清楚
了,但是得化一些时间来看。
在驱动程序中实现的ioctl函数体内,实际上是有一个switch{case}结构,每一个case对
应一个命令码,做出一些相应的操作。怎么实现这些操作,这是每一个程序员自己的事
情,因为设备都是特定的,这里也没法说。关键在于怎么样组织命令码,因为在ioctl中
命令码是唯一联系用户程序命令和驱动程序支持的途径。
命令码的组织是有一些讲究的,因为我们一定要做到命令和设备是一一对应的,这样才不
会将正确的命令发给错误的设备,或者是把错误的命令发给正确的设备,或者是把错误的
命令发给错误的设备。这些错误都会导致不可预料的事情发生,而当程序员发现了这些奇
怪的事情的时候,再来调试程序查找错误,那将是非常困难的事情。
所以在Linux核心中是这样定义一个命令码的:
____________________________________
| 设备类型 | 序列号 | 方向 |数据尺寸|
|----------|--------|------|--------|
| 8 bit | 8 bit |2 bit |8~14 bit|
|----------|--------|------|--------|

这样一来,一个命令就变成了一个整数形式的命令码。但是命令码非常的不直观,所以
Linux Kernel中提供了一些宏,这些宏可根据便于理解的字符串生成命令码,或者是从
命令码得到一些用户可以理解的字符串以标明这个命令对应的设备类型、设备序列号、数
据传送方向和数据传输尺寸。

这些宏我就不在这里解释了,具体的形式请读者察看Linux核心源代码中的和,文件里给
除了这些宏完整的定义。这里我只多说一个地方,那就是""幻数""。
幻数是一个字母,数据长度也是8,所以就用一个特定的字母来标明设备类型,这和用一
个数字是一样的,只是更加利于记忆和理解。就是这样,再没有更复杂的了。
更多的说了也没有,读者还是看一看源代码吧,推荐各位阅读《Linux 设备驱动程序》所
带源代码中的short一例,因为它比较短小,功能比较简单,可以看明白ioctl的功能和细
节。

四、 cmd参数如何得出
这里确实要说一说,cmd参数在用户程序端由一些宏根据设备类型、序列号、传送方向、
数据尺寸等生成,这个整数通过系统调用传递到内核中的驱动程序,再由驱动程序使用解
码宏从这个整数中得到设备的类型、序列号、传送方向、数据尺寸等信息,然后通过
switch{case}结构进行相应的操作。
要透彻理解,只能是通过阅读源代码,我这篇文章实际上只是一个引子。Cmd参数的组织
还是比较复杂的,我认为要搞熟它还是得花不少时间的,但是这是值得的,驱动程序中最
难的是对中断的理解。

五、 小结
ioctl其实没有什么很难的东西需要理解,关键是理解cmd命令码是怎么在用户程序里生成
并在驱动程序里解析的,程序员最主要的工作量在switch{case}结构中,因为对设备的
I/O控制都是通过这一部分的代码实现的。
分享到:
评论

相关推荐

    linux内核 0.11版本源码 带中文注释

    * 我们需要下面这些内嵌语句 - 从内核空间创建进程(forking)将导致没有写时复制(COPY ON WRITE)!!! * 直到一个执行execve 调用。这对堆栈可能带来问题。处理的方法是在fork()调用之后不让main()使用 * 任何堆栈...

    Linux驱动程序开发学习

    学会写简单的makefile 2. 编一应用程序,可以用makefile跑起来 3.... 你会发现最基本的你已经知道了, 大的框架都是一样的, 无非是read, write, ioctl等函数的实现, 但里面包含了很多很多细小的实现细节是之 ...

    LINUX编程白皮书 (全集)

    第一部分 Linux内核 前言 第1章 硬件基础与软件基础 6 1.1 硬件基础 6 1.1.1 CPU 7 1.1.2 存储器 8 1.1.3 总线 8 1.1.4 控制器和外设 8 1.1.5 地址空间 9 1.1.6 时钟 9 1.2 软件基础 9 1.2.1 计算机语言 9 1.2.2 ...

    linux操作系统培训资料.pptx

    如果我们想控制串口的速率、校验位、码位的长度,我们只需要调用ioctl函数,然后传入相应的数据就可以了。 linux操作系统培训资料全文共28页,当前为第8页。 Linux文件管理 Linux系统中使用的文件类型 目前linux...

    Linux编程从入门到精通

    linux内核编程 目 录 雷蒙序 简介 Linux文档工程小组“公告” 译者序 第一部分 Linux内核 前言 第1章 硬件基础与软件基础 6 1.1 硬件基础 6 1.1.1 CPU 7 1.1.2 存储器 8 1.1.3 总线 8 1.1.4 控制器和外设 8 ...

    imx6ull_dma驱动程序模块和用户测试程序代码Linux

    1、一是使用内核驱动模块的/dev/sdma_test中的ioctl函数将希望传入数据的 源地址映射到了内核空间, 用户程序中对该地址中的内容所做的更改都会在启动DMA传输后传输到DMA 的目的地址中。可以从内核驱动模块的打印中...

    linux网络编程-宋敬彬-part3

    1.5.1 Linux内核的主要模块 7 1.5.2 Linux的文件结构 9 1.6 GNU通用公共许可证 10 1.6.1 GPL许可证的历史 10 1.6.2 GPL的自由理念 10 1.6.3 GPL的基本条款 11 1.6.4 关于GPL许可证的争议 12 1.7 Linux...

    linux网络编程-宋敬彬-part2

    1.5.1 Linux内核的主要模块 7 1.5.2 Linux的文件结构 9 1.6 GNU通用公共许可证 10 1.6.1 GPL许可证的历史 10 1.6.2 GPL的自由理念 10 1.6.3 GPL的基本条款 11 1.6.4 关于GPL许可证的争议 12 1.7 Linux...

    JNI模拟系统事件

    原理是在jni中通过Linux内核的ioctl函数和c语言函数(memset、write)来实现对设备的I/O通道进行管理的。所谓对I/O通道进行管理,就是对设备的一些特性进行控制,例如串口的传输波特率、马达的转速等等。

    linux编程白皮书

    第一部分 Linux内核 前言 第1章 硬件基础与软件基础 6 1.1 硬件基础 6 1.1.1 CPU 7 1.1.2 存储器 8 1.1.3 总线 8 1.1.4 控制器和外设 8 1.1.5 地址空间 9 1.1.6 时钟 9 1.2 软件基础 9 1.2.1 计算机语言 9 1.2.2 ...

    linux设备驱动程序第三版

    1. Linux 设备驱动第三版 .................................................................................................................... 5 2. 第 1 章 设备驱动简介 ....................................

    Linux C 一站式学习

    Linux系统编程 28. 文件与I/O 1. 汇编程序的Hello world 2. C标准I/O库函数与Unbuffered I/O函数 3. open/close 4. read/write 5. lseek 6. fcntl 7. ioctl 8. mmap 29. 文件系统 1. 引言 2. ext2文件系统 2.1. 总体...

    linux驱动开发流程

    每个系统调用中都有一个与之对应的函数(open、release、read、write、ioctl等),在字符驱动程序中,这些函数集合在一个file_operations类型的数据结构中。以一个键盘驱动程序为例: struct file_operations Key...

    linux网络编程-宋敬彬-part1

    1.5.1 Linux内核的主要模块 7 1.5.2 Linux的文件结构 9 1.6 GNU通用公共许可证 10 1.6.1 GPL许可证的历史 10 1.6.2 GPL的自由理念 10 1.6.3 GPL的基本条款 11 1.6.4 关于GPL许可证的争议 12 1.7 Linux...

    linux设备驱动程序

    《LINUX设备驱动程序(第3版)》已针对Linux内核的2610版本彻底更新过了。内核的这个版本针对常见任务完成了合理化设计及相应的简化,如即插即用、利用sysfs文件系统和用户空间交互,以及标准总线上的多设备管理等等。...

    LINUX编程白皮书

    第一部分 Linux内核 前言 第1章 硬件基础与软件基础 6 1.1 硬件基础 6 1.1.1 CPU 7 1.1.2 存储器 8 1.1.3 总线 8 1.1.4 控制器和外设 8 1.1.5 地址空间 9 1.1.6 时钟 9 1.2 软件基础 9 1.2.1 计算机语言 9 1.2.2 ...

    Android驱动开发权威指南

    第3章Linux内核综述 3.1 OS基本概念 3.1.1多用户系统 3.1.2用户和组 3.1.3进程 3.1.4 Linux单核架构 3.2 Linux内核综述 3.2.1进程/内核模型综述 3.2.2内存管理综述 3.2.3文件系统综述 3.2.4设备驱动简述 第4章Linux...

    imx6ull_dma_camera_lcd.zip

    1、一是使用内核驱动模块的/dev/sdma_test中的ioctl函数将希望传入数据的 源地址映射到了内核空间, 用户程序中对该地址中的内容所做的更改都会在启动DMA传输后传输到DMA 的目的地址中。可以从内核驱动模块的打印中...

    Linux编程白皮书

    第一部分 Linux内核 前言 第1章 硬件基础与软件基础 6 1.1 硬件基础 6 1.1.1 CPU 7 1.1.2 存储器 8 1.1.3 总线 8 1.1.4 控制器和外设 8 1.1.5 地址空间 9 1.1.6 时钟 9 1.2 软件基础 9 1.2.1 计算机语言 9 1.2.2 ...

Global site tag (gtag.js) - Google Analytics