ioctl 与 Linux 中的内核模块

Posted

技术标签:

【中文标题】ioctl 与 Linux 中的内核模块【英文标题】:ioctl vs kernel modules in Linux 【发布时间】:2020-10-30 13:54:44 【问题描述】:

我知道内核模块是用来写device drivers的。您可以在 Linux 内核中添加新的system calls,并使用它与其他设备进行通信。

我还读到ioctl是linux中用来实现系统调用的系统调用,默认情况下在内核中是不可用的。

我的问题是,你为什么不直接为你的设备写一个新的kernel module 而不是使用ioctl?为什么ioctl b 在存在内核模块的地方有用?

【问题讨论】:

ioctl 用于在特定设备上执行特定于设备的操作。系统调用用于执行与设备无关的全新操作。 【参考方案1】:

无论哪种情况,您都需要编写内核驱动程序,但您可以在添加新系统调用和添加 ioctl 之间进行选择。

假设您要添加一项功能来获取视频捕获设备的调谐器设置。

如果您将其实现为系统调用:

你不能只加载一个模块,你需要改变内核本身 数百个驱动程序每个都可以添加数十个系统调用,从而将数以千计的全局函数混杂在一起,这些函数必须永远保留。 为了使驱动程序有任何影响,您需要让内核维护人员相信这个负担是值得的。 您需要将定义上传到 glibc,并且人们必须先升级才能为其编写程序

如果您将其实现为 ioctl:

您可以为现有内核构建模块并让用户加载它,而无需让内核维护人员参与进来 所有函数都是适用的头文件中的每个驱动程序的简单常量,可以在其中轻松添加或删除它们 每个人都可以通过包含标题开始使用它进行编程

由于 ioctl 更简单、更灵活,并且完全适用于所有这些驱动程序特定的函数调用,因此这通常是首选方法。

【讨论】:

【参考方案2】:

我还读到 ioctl 是 linux 中用于实现系统调用的系统调用,默认情况下在内核中不可用。

这是不正确的。

System calls(对于 Linux)列在 syscalls(2) 中(user space 和内核域之间有数百个),ioctl(2) 是其中一个。另请阅读wikipage on ioctl 和Unix philosophy 和Linux Assembler HowTo

实际上,ioctl 主要用于设备文件,并且用于不是read(2) 或write(2) 字节的东西。 例如,通过向/dev/audio 写入字节来发出声音,但要更改音量,您将使用一些ioctl。另请参阅 fcntl(2) 扮演类似角色。

输入/输出也可能通过mmap(2) 和相关的虚拟地址空间系统调用发生(以某种方式间接...)。

更多信息,请阅读Advanced Linux ProgrammingOperating Systems: Three Easy Pieces。查看Osdev 以获取有关编写自己的操作系统的更多提示。

内核模块可以实现新设备,或新的ioctl 等...更多信息请参见kernelnewbies。我倾向于相信它有时可能会添加一些新的系统调用(但这在旧的 linux kernels 中是错误的,比如 3.x 的)

Linux 主要是open source。请下载然后查看源代码。另见Linux From Scratch。

IIRC,Linux 内核 1.0 没有任何内核模块。但那是在 1995 年左右。

【讨论】:

and used for things which are not a read(2) or a write(2) of bytes 可以举个例子吗?不知道它们可能是什么。 顺便说一句,我从这里复制了我的声明:tuxthink.blogspot.com/2011/01/creating-ioctl-command.html。所以是错的? 我相信您需要阅读数百页才能获得直觉。 but to change the volume you'll use some ioctl,为什么没有由同一个声音驱动程序开发的独特系统调用来做到这一点? 这是一个约定俗成的问题。 Linus Torvards 决定(与其他人)不这样做(出于良好的性能原因)。在他之前,Kernighan 和 Ritchie 为第一个 Unix 系统这样做了。我从未见过他们中的任何一个,所以我无法解释他们的想法。随意编写自己的操作系统(可能需要十年时间)。更多信息请见osdev.org

以上是关于ioctl 与 Linux 中的内核模块的主要内容,如果未能解决你的问题,请参考以下文章

自定义 linux 内核的 ioctl 突然停止响应并在几分钟后重新启动

分析 Linux 内核模块

内核栈溢出

在内核模式和用户模式之间使用ioctl通信

Linux 内核 4.8.0-53-generic Linux Mint 64 位中 IOCTL 函数的不兼容指针初始化错误

我的内核模块使用了多少内存?