由医生。 ,ioctl 签名是int ioctl(int fd, int request, ...)
。 request是ioctl的代码。
有什么方法可以知道我的 Linux 中可用的所有可能的 ioctl 请求代码是什么?也许要知道每个代码映射到哪个内核模块?
答案1
ioctl
通过使用内核源代码vim
和ctags
程序可以找到所有定义。我只使用我的工具箱中的工具,您可以使用其他工具 - 也许是 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
。然后进一步跳转到头文件中的具体命令,查看定义和注释。