news 2026/6/6 14:18:51

第6章:字符设备驱动的高级操作7:The Implementation of the ioctl Commands

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
第6章:字符设备驱动的高级操作7:The Implementation of the ioctl Commands

In continuation of the previous text 第6章:字符设备驱动的高级操作6:Capabilities and Restricted Operations let’s GO ahead.

The Implementation of the ioctl Commands

The scull implementation of ioctl only transfers the configurable parameters of the device and turns out to be as easy as the following:

scull 驱动的 ioctl 实现仅用于传输设备的可配置参数,实现起来非常简单,代码如下:

switch(cmd) { case SCULL_IOCRESET: scull_quantum = SCULL_QUANTUM; scull_qset = SCULL_QSET; break; case SCULL_IOCSQUANTUM: /* Set: arg 指向数值 */ if (! capable (CAP_SYS_ADMIN)) return -EPERM; retval = __get_user(scull_quantum, (int __user *)arg); break; case SCULL_IOCTQUANTUM: /* Tell: arg 就是数值 */ if (! capable (CAP_SYS_ADMIN)) return -EPERM; scull_quantum = arg; break; case SCULL_IOCGQUANTUM: /* Get: arg 指向存放结果的指针 */ retval = __put_user(scull_quantum, (int __user *)arg); break; case SCULL_IOCQQUANTUM: /* Query: 返回它(正数) */ return scull_quantum; case SCULL_IOCXQUANTUM: /* eXchange: 使用 arg 作为指针 */ if (! capable (CAP_SYS_ADMIN)) return -EPERM; tmp = scull_quantum; retval = __get_user(scull_quantum, (int __user *)arg); if (retval == 0) retval = __put_user(tmp, (int __user *)arg); break; case SCULL_IOCHQUANTUM: /* sHift: 类似于 Tell + Query */ if (! capable (CAP_SYS_ADMIN)) return -EPERM; tmp = scull_quantum; scull_quantum = arg; return tmp; default: /* 冗余检查,因为 cmd 已通过 MAXNR 校验 */ return -ENOTTY; } return retval;

scull also includes six entries that act on scull_qset. These entries are identical to the ones for scull_quantum and are not worth showing in print. The six ways to pass and receive arguments look like the following from the caller’s point of view (i.e., from user space):

scull 驱动还包含六个操作 scull_qset 的入口。这些入口与操作 scull_quantum 的代码完全相同,因此不再赘述。

从调用者(即用户空间)的角度来看,六种传递和接收参数的方式如下所示:

int quantum; ioctl(fd, SCULL_IOCSQUANTUM, &quantum); /* 通过指针设置 */ ioctl(fd, SCULL_IOCTQUANTUM, quantum); /* 通过值设置 */ ioctl(fd, SCULL_IOCGQUANTUM, &quantum); /* 通过指针获取 */ quantum = ioctl(fd, SCULL_IOCQQUANTUM); /* 通过返回值获取 */ ioctl(fd, SCULL_IOCXQUANTUM, &quantum); /* 通过指针交换 */ quantum = ioctl(fd, SCULL_IOCHQUANTUM, quantum); /* 通过值交换 */

Of course, a normal driver would not implement such a mix of calling modes. We have done so here only to demonstrate the different ways in which things could be done. Normally, however, data exchanges would be consistently performed, either through pointers or by value, and mixing of the two techniques would be avoided.

当然,一个正常的驱动程序不会实现如此混合的调用模式。我们在这里这样做只是为了演示可以采用的各种不同方式。然而在实际开发中,数据交换应保持一致,要么统一通过指针,要么统一通过值,应避免两种方式混用。

补充说明:

1. 代码核心逻辑梳理

这段代码是scull 驱动 ioctl 的核心处理函数,根据不同的命令 cmd 执行不同操作:

  • 重置设备:将量子大小和量子集大小恢复为默认值。
  • 设置参数:分为指针传参(S)和直接传值(T),必须检查管理员权限
  • 获取参数:分为指针回写(G)和直接返回(Q),无需权限
  • 原子交换:先保存旧值,读取新值,再写回旧值,实现原子操作。

2. 六种命令模式深度解析

驱动实现了6 种参数交互方式,对应前缀含义:

  • S (Set):用户传指针,驱动从用户空间读取值。
  • T (Tell):用户直接传整数,驱动直接使用 arg。
  • G (Get):驱动将值写入用户提供的指针
  • Q (Query):驱动直接将结果作为返回值返回。
  • X (eXchange):原子交换,用户传指针,传入新值、取回旧值。
  • H (sHift):原子切换,用户传值,设置新值、返回旧值。

3. 权限控制关键点

  • 所有 “设置 / 修改” 操作:必须检查CAP_SYS_ADMIN权限。
  • 所有 “读取 / 查询” 操作不检查权限,任何用户均可查询。
  • 无权限时返回-EPERM,表示 “操作不允许”。

4. 内核函数解释

  • __get_user:从用户空间读取一个整数(已提前校验地址,高效版)。
  • __put_user:向用户空间写入一个整数(已提前校验地址,高效版)。
  • capable():检查当前进程是否拥有指定特权能力。

5. 为什么实际驱动不要混合模式?

原文明确指出:真实驱动不应混合多种传参方式。 原因:

  • 容易造成用户态程序出错、传参错误。
  • 降低代码可读性、可维护性。
  • 容易引发安全漏洞。

标准推荐做法

  • 所有命令统一使用指针传参(最安全、最通用)。
  • 或统一使用返回值获取结果

6. 错误码总结

  • -EPERM:权限不足。
  • -EFAULT:用户空间地址非法(由 __get_user/__put_user 返回)。
  • -ENOTTY:不支持该 ioctl 命令。

7. 原子交换(X / H 命令)的意义

这两个命令实现了原子的 “读 - 改 - 写”

  • 旧值保存、新值写入、旧值返回,全程不可被打断。
  • 适用于多线程并发修改配置的场景。
  • 无需额外加锁,提高效率。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/6 14:18:39

Simple Live:一站式聚合直播平台,让看直播从此简单

Simple Live:一站式聚合直播平台,让看直播从此简单 【免费下载链接】dart_simple_live 简简单单的看直播 项目地址: https://gitcode.com/GitHub_Trending/da/dart_simple_live 还在为在不同直播平台间来回切换而烦恼吗?Simple Live 为…

作者头像 李华
网站建设 2026/6/6 14:17:59

Lynx-native调试技巧:快速定位跨平台应用中的常见问题

Lynx-native调试技巧:快速定位跨平台应用中的常见问题 【免费下载链接】lynx-native Run native apps for iOS and Android using JavaScript. 项目地址: https://gitcode.com/gh_mirrors/ly/lynx-native Lynx-native调试技巧是每位跨平台应用开发者必须掌握…

作者头像 李华
网站建设 2026/6/6 14:17:59

Tcl二进制数据处理:binary format与binary scan命令实战指南

1. 项目概述:二进制数据处理的核心工具在嵌入式开发、FPGA/CPLD逻辑验证、通信协议解析乃至自动化测试脚本编写中,我们常常需要与硬件寄存器、原始数据包或二进制文件打交道。这些数据不像文本那样直观,它们由一个个字节构成,直接…

作者头像 李华
网站建设 2026/6/6 14:16:36

CSDN AI标题优化不是“换词游戏”:揭秘其背后融合的3层Ranking模型(Query理解层/内容表征层/用户反馈强化层)

更多请点击: https://codechina.net 第一章:CSDN AI数字营销的AI优化文章标题后提升搜索排名原理是什么? CSDN AI数字营销平台通过深度语义建模与搜索引擎行为数据融合,实现对技术类文章标题的智能优化。其核心原理在于将标题生成…

作者头像 李华
网站建设 2026/6/6 14:16:18

从“大蒜挡手机”看硬件创业的供应链风险管理与地缘政治博弈

1. 一个看似荒诞的标题引发的产业思考 “山东大蒜帮助中国挡住了日本手机?”——这标题乍一看,确实像极了地摊文学或网络段子,充满了戏剧性的夸张。我第一次在《冰眼看日本》这本书里读到这个说法时,也是将信将疑。但作为一名在电…

作者头像 李华
网站建设 2026/6/6 14:14:28

CorridorKey:基于神经网络的物理精确绿幕抠像终极解决方案

CorridorKey:基于神经网络的物理精确绿幕抠像终极解决方案 【免费下载链接】CorridorKey Perfect Green Screen Keys 项目地址: https://gitcode.com/gh_mirrors/co/CorridorKey 在视觉特效(VFX)和影视后期制作领域,绿幕抠…

作者头像 李华