在计算中,ioctl 是对装置特定的输入/输出操作和其他不能用常规系统调用表达的操作的系统调用。 它需要一个指定请求代码的参数; 调用的效果完全取决于请求代码。 请求代码通常是特定于装置的。

例如,可以指示物理装置弹出光碟的 CD-ROM 装置,则驱动程式将提供 ioctl 请求代码来执行此操作。 与装置无关的请求代码有时用于让用户空间访问仅由核心系统软件使用或仍在开发中的内核功能。 ioctl 系统调用以该名称首次出现在 Unix 版本 7 中。 大多数 Unix 和类 Unix 系统都支持它,包括 LinuxmacOS,但可用的请求代码因系统而异。Microsoft Windows 在其 Win32 API 中提供了一个类似的函数,名为“DeviceIoControl”。

背景

传统的操作系统可以分为两层,用户空间内核文本编辑器等应用程式代码驻留在用户空间,而操作系统的底层设施(如网络堆栈)驻留在内核中。 内核代码处理敏感资源并实现应用程式之间的安全性和可靠性屏障; 因此,操作系统会阻止用户模式应用程式直接访问内核资源。 用户空间应用程式通常通过系统调用向内核发出请求,其代码位于内核层。

系统调用通常采用“系统调用向量”的形式,其中用索引号指示所需的系统调用。 例如,exit() 可能是 1 号系统调用,而 write() 号是 4。系统调用向量然后用于为请求找到所需的内核函数。 这样,传统的操作系统通常会向用户空间提供数百个系统调用。

尽管系统调用是访问标准内核设施的权宜之计,但系统调用有时不适用于访问非标准硬件外围装置。 必然地,大多数硬件外围装置(也称为装置)只能在内核中直接寻址。 但是用户代码可能需要直接与装置通信; 例如,管理员可能会在以太网接口上配置媒体类型。 现代操作系统支持多种装置,其中许多装置提供大量功能。 内核设计者可能没有预见到其中一些设施,因此内核很难提供使用这些装置的系统调用。

为了解决这个问题,内核被设计成可扩展的,并且可以接受一个额外的模块,称为装置驱动程式,它运行在内核空间,可以直接寻址装置。 ioctl 接口是一个单一的系统调用,用户空间可以通过它与装置驱动程式进行通信。 装置驱动程式上的请求根据此 ioctl 系统调用进行引导,通常通过装置句柄和请求编号进行引导。 因此,基本内核可以允许用户空间访问装置驱动程式,而无需了解装置支持的设施,也不需要难以管理的大量系统调用。

使用

硬件装置配置

ioctl 的一个常见用途是控制硬件装置。例如,在 Win32 系统上,ioctl 调用可以与 USB 装置通信,或者它们可以发现附加存储装置的驱动器几何资讯。

OpenBSDNetBSD 上,bio(4) 伪装置驱动程式和 bioctl 实用程序使用 ioctl 在类似于 ifconfig 的统一供应商不可知接口中实现 RAID 卷管理。[1][2]在 NetBSD 上,ioctl 也被 sysmon 框架使用。[3]

终端

在面向最终用户的应用程式中,ioctl 的一种用途是终端 I/O。 Unix 操作系统传统上大量使用命令行界面。 Unix 命令行界面建立在伪终端 (ptys) 之上,它模拟硬件文本终端,例如 VT100s。 使用 ioctl 调用,可以像硬件装置一样控制和配置 pty。 例如,pty 的窗口大小是使用 TIOCSWINSZ 调用设置的。TIOCSTI(terminal I/O control,模拟终端输入)的ioctl函数可以将一个字符压入装置流

参考文献

  1. ^ Super User's BSD Cross Reference: /OpenBSD/share/man/man4/bio.4. bxr.su. [2023-01-09]. (原始内容存档于2022-10-01). 
  2. ^ Super User's BSD Cross Reference: /OpenBSD/sbin/bioctl/bioctl.8. bxr.su. [2023-01-09]. (原始内容存档于2023-01-09). 
  3. ^ sysmon(4) — system monitoring and power management interface. NetBSD. An ioctl(2) interface available via /dev/sysmon.