Linux设备驱动 | 系统IO之ioctl函数详解

作者:世至其美

原文地址:https://hqber.com

1. 定义:

ioctl是设备驱动程序中对设备的I/O通道进行管理的函数。

在用户空间, ioctl 系统调用的原型:

int ioctl(int fd, unsigned long cmd, ...);

ioctl 驱动方法有和用户空间版本不同的原型:

int (*ioctl) (struct inode *inode, struct file *filp, unsigned int cmd,unsigned long arg);
2. 定义命令编号规则(cmd)

定义 ioctl 命令号使用 4 个位字段(

  • type
    幻数,只是选择一个号码(在参考了 ioctl-number.txt 之后)并且使用它在整个驱动 中,这个成员是 8 位宽(_IOC_TYPEBITS)。
  • number
    序数(顺序编号), 它是 8 位(_IOC_NRBITS)宽。
  • direction
    数据传送的方向,数据传送是从应用程序的观点来看待的。
    • _IOC_NONE:没有数据传输
    • _IOC_READ:从设备读数据
    • _IOC_WRITE:从设备写数据
    • _IOC_READ | _IOC_WRITE:双向传输数据
  • size
    用户数据的大小,与体系结构有关。常常是 13 或者14 位,你通过宏 _IOC_SIZEBITS 中找到它的值。size字段不是必须的,内核不会检查这个字段,正确使用size可帮助检测用户空间程序的错误并使你实现向后兼容。
2.1 构造命令编号

  • _IO(type,nr):构造无参数的命令编号
  • _IOR(type, nre,datatype):构造给从驱动中读数据的命令编号
  • _IOW(type,nr,datatype):构造给从驱动中写数据的命令编号
  • _IOWR(type,nr,datatype):构造给从驱动中读写数据的命令编号

tips:type 和 number 成员作为参数被传递, 并且 size 成员通过应用 sizeof 到 datatype 参数而得到。

2.2 解码命令编号

可通过命令编号进行解码各个字段

  • _IOC_DIR(nr)
  • _IOC_TYPE(nr)
  • _IOC_NR(nr)
  • _IOC_SIZE(nr)
2.3 预定义的命令

可用于任何文件(普通、设备、FIFO和套接字) 的命令

只用于普通文件发出的命令

特定于文件系统类型的命令

3. arg参数

如果它是一个整数,可以直接使用。如果它是一个指针, 我们必须确保用户地址是有效的。试图读取一个没验证过的用户提供的指针可能导致不正确的行为, 一个内核 oops、系统崩溃、或者安全问题。驱动的责任是对每一个它使用的用户空间地址进行正确的检查, 如果它是无效的,则返回一个错误。

地址校验(不传送数据)由函数 access_ok实现,它定义在

int access_ok(int type, const void *addr, unsigned long size);
4. 返回值
  • ioctl 的实现常常是一个 switch 语句, 基于命令号. 但是当命令号没有匹配一个有效的,一般返回值为:
    • ENIVAL(“Invalid argument”):命令参数确实不是一个有效的
5. 单个数据
5.1 传输单个数据
  • put_user(datum, ptr)
    检查来确保这个进程能够写入给定的内存地址。它在成功时返回 0,并且在错误时返回 -EFAULT。
  • ___put_user(datum, ptr)
    进行更少的检查(它不调用 access_ok),但是仍然能够失败如果被指向的内存对用户是不可写的。
5.2 接收单个数据
  • get_user(local, ptr)
    应当只用在已经使用 access_ok 校验过的地址,从用户空间接收单个数据,获取的值存储于本地变量 local。
  • __get_user(local, ptr)
    进行更少的检查(它不调用 access_ok),从用户空间接收单个数据,获取的值存储于本地变量 local。

注意:传输/接收多个数据到用户空间可使用copy_to_user和copy_from_user函数。

6. 权能和受限

权能就是对权限进行管理分配,全部的权能操作在

  • CAP_DAC_OVERRIDE:越过文件或目录的访问限制(数据访问控制或者 DAC)的能力。
  • CAP_NET_ADMIN:进行网络管理任务的能力, 包括那些能够影响网络接口的。
  • CAP_SYS_MODULE:载入或卸载内核模块的能力。
  • CAP_SYS_RAWIO:进行 "裸“ I/O 操作的能力,例子包括存取设备端口或者直接和 USB 设备通讯。
  • CAP_SYS_ADMIN:截获的能力, 提供访问许多系统管理操作的途径。
  • CAP_SYS_TTY_CONFIG:进行 tty 配置任务的能力。

设备驱动程序应该检查调用进程是否有合适的权能,如果不进行检查,将影响系统稳定性和安全性。

作者:世至其美

原文地址:https://hqber.com

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值