获取所有 ioctl 代码以及它们映射的模块

获取所有 ioctl 代码以及它们映射的模块

由医生。 ,ioctl 签名是int ioctl(int fd, int request, ...)。 request是ioctl的代码。

有什么方法可以知道我的 Linux 中可用的所有可能的 ioctl 请求代码是什么?也许要知道每个代码映射到哪个内核模块?

答案1

ioctl通过使用内核源代码vimctags程序可以找到所有定义。我只使用我的工具箱中的工具,您可以使用其他工具 - 也许是 Netbeans 或 Eclipse 等 IDE。本质是一样的。

示范: (您可以下载此.gif文件并通过GIMP打开它,然后所有帧都将不受时间限制) 在此输入图像描述

解释:

1)我想,除了深入内核源码,我们没有其他办法。存在不同的手册,请检查apropos ioctl,但它们要么不完整,要么已经过时。因此,最可靠的方法是查看源代码(如果您没有模块创建者的文档)。用户进程使用ioctl系统调用向内核模块发送不同的命令。该模块对每个模块都有定义和注释读写控制命令。我们的任务是找到他们。

注意开始

您应该使用与用户相同的内核源版本glibc,而不是系统上的当前内核,因为glibc标头用于编译用户程序。因此,如果您将使用最后一个内核源(或其他与内核源不同的源glibc),结果可能是错误的。

glibc要在 Ubuntu 上查找标头版本,请执行以下操作:

dpkg -l linux-libc-dev*

结果:

ii  linux-libc-dev:amd64  4.15.0-50.54    amd64           Linux Kernel Headers for development

将带有 Ubuntu 补丁的内核源代码从存储库下载到当前目录(在 Ubuntu 上):

apt-get source linux-source-4.15.0

注释结束

2) 读写控制命令在模块头文件中定义 -一些_name.h。它们只是数字,可以通过特殊的宏来计算:

#define "ioctl name" __IOX("major number","command number","argument type")

文档:

如果要向内核添加新的 ioctl,则应该使用中定义的 _IO 宏linux/ioctl.h:

_IO    an ioctl with no parameters
_IOW   an ioctl with write parameters (copy_from_user)
_IOR   an ioctl with read parameters  (copy_to_user)
_IOWR  an ioctl with both write and read parameters.

但有些ioctl定义不遵循这个规定,并且与通常的宏没有什么不同,例如驱动程序的情况tty

#define TCGETS      0x5401

所以,我们不能只是grep头文件。

3)定义的读写控制命令在模块源代码文件中使用 -一些_name.c。有特殊的函数 - handler,每个函数都会调用它读写控制要求。它需要读写控制number 作为参数并将程序执行切换到相应的分支,例如:

switch(ioctl_cmd){
    case IOCTL_ONE:
        processing;
        break;
    case IOCTL_TWO:
        processing;
        break;
    case IOCTL_THREE:
        processing;
        break;
}

4)读写控制处理程序存储在.unlocked_ioctl以下字段中file_operations struct

static const struct file_operations sonypi_misc_fops = {
    ...      
    .unlocked_ioctl = sonypi_misc_ioctl,

因此,我们可以在源代码中找到这个赋值,通过ctags程序跳转到处理函数定义处查看 读写控制建设中的分支机构switch。然后进一步跳转到头文件中的具体命令,查看定义和注释。

相关内容