【通俗易懂】详解 ioctl 函数是如何操控底层的

ioctl函数用于用户空间与内核空间的驱动模块交互,分为数据读写和状态控制。命令码包含数据传输方向、数据大小、设备类型和功能码,通过宏定义如_IOW进行封装。在用户空间,通过ioctl函数传递命令码和数据地址,内核空间则通过file_operations结构体中的ioctl函数指针接收并执行相应操作。文章提供了一个LED控制的例子来说明ioctl的使用过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【通俗易懂】详解 ioctl 函数是如何操控底层的

1. ioctl函数的意义

​ 设计出 ioctl 函数的主要原因是:内核设计者希望将用户空间和内核空间的驱动模块的交互分成两部分:数据读写以及状态控制。引入 ioctl 函数之后,数据读写和状态控制将被区分开进行管理,互不干扰。

​ 另外,ioctl函数在使用时,要求用户按照内核特定的方式进行命令码的封装。此后,应用层工程师和内核驱动工程师都可以按照同一套封装标准进行命令码的封装和解析,实现了应用层和内核空间更好的对接。

2. ioctl函数的形象理解

​ 使用 ioctl 函数,本质上就是用户空间向内核空间提交一段具有特定含义的命令码,内核空间根据内核规定好的方式,对命令码进行解析,执行对应的底层操作。即:命令码和底层操作应该是一一对应的,一个具体的命令码就代表了一次底层操作的全部信息

3. ioctl 函数命令码的解析

ARM架构下的Linux内核,每个命令码都由 32bit 组成:

bit 位数 31 : 30 29 : 16 15 : 8 7 : 0
代表含义 数据传输方向 数据传递大小 设备类型码 功能码
占用bit数 2 14 8 8

3.1 数据传输方向

​ 用户从内核读取数据 or 用户向内核传递数据
​ [00] 表示不传递数据,内核宏定义为: _IO
​ [10] 表示只读,内核定义为: _IOR
​ [01] 表示只写,内核宏定义为: _IOW
​ [11] 表示可读可写,内核宏定义为: _IOWR

3.2 数据传递大小

​ 用户空间和内核传递的数据的大小
当使用宏定义进行命令码封装的时候,这边就必须填写数据类型:
​ 例如无符号四字节就要填 int,一个长度为20的字符数组就要写 char [20]
​ 原因是:可以从底层封装中得知:这个地方的数据大小,底层是通过 sizeof() 实现的,且这边必须填一个常量,因此要填入数据类型

3.3 设备类型码

​ 每一个驱动通过一个唯一的字符来代表,只是为了区分开不同的设备
​ 例如:LED驱动用 ‘L’ 代表,串口驱动用 ‘U’ 代表

3.4 功能码

​ 不同的功能通过功能码进行区分,这个自己指定即可
​ 例如:开启LED的功能码为10,关闭LED的功能码为20

4. 使用内核定义好的宏进行命令码封装

例如要封装一个:让LED亮或灭的命令码(可指定哪一盏LED),思路如下:

  1. 由于要制定具体是哪一盏LED亮或灭,因此必须要传递数据(比如1表示LED1,2表示LED2等)这边是往内核写数据,因此方向位写 01(只写)
  2. 由于要向内核传递是操作第几盏LED,因此这边可以传递一个无符号整型数据(unsigned int)因此数据传递大小位写 00000000000100(4)
  3. 给 LED 设备类型取一个类型码,此处随意,可取为 ‘L’,它的 ascii 码为 76,因此设备类型码位写 01001100(76)
  4. 给具体功能取一个功能码,此处随意,可以用 10 表示亮灯功能,用 11 表示灭灯功能,因此功能码位写 00001010(10 亮灯)或者 00001011(11 灭灯)

综上所述,手动封装一个命令码的结果是:
亮灯:(0b) 01 00000000000100 01001100 00001010
灭灯:(0b) 01 00000000000100 01001100 00001011
用宏定义封装即为:

#define 	LED_ON_FUNC 	0b01000000000001000100110000001010
#define 	LED_OFF_FUNC 	0b01000000000001000100110000001011

使用内核定义好的宏定义可以大大简化命令码封装过程,内核的宏定义如下:

#define _IO(type,nr)		 _IOC(_IOC_NONE,(type),(nr),0)							// 不传输数据
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值