哪个驱动程序正在处理我的 IOCTL

Which driver is handling my IOCTL

我正在打开这样的套接字: skfd = socket( AF_INET, SOCK_DGRAM, 0 ); 然后在 skfd 上执行 ioctl,例如:ioctl(skfd, SIOCETHTOOL, &ifr)
我想知道哪个驱动程序在我的内核中处理这个 IOCTL。
我知道如果它是一个字符驱动程序,我可以查找我正在打开的文件的主编号,然后执行 cat /proc/devices 查找哪个驱动程序注册了该主编号。
这里一定是某种类似的方式。

您正在对代表套接字的文件描述符调用 ioctl。如果您检查 net/socket.c 文件,您会发现 socket_file_ops 结构将 sock_ioctl 定义为 ioctl 回调。对于 SIOCETHTOOL,此函数将调用 sock_do_ioctl,而后者(在检查此特定套接字类型(AF_INET - af_inet.c、inet_ioctl 函数之后)不处理这个 ioctl 本身)将调用 dev_ioctl,它可以通过调用 dev_ethtool 来处理 SIOCETHTOOL。如果你的驱动定义了ethtool_ops,这应该是支持的。

现在找到哪个设备驱动程序支持您的网络接口是另一回事,但这并不难。一种方法是使用 sysfs,只需检查这个符号链接指向什么(用您的接口名称替换 eth0):

readlink /sys/class/net/eth0/device/driver/module
../../../../module/e1000e

所以我的以太网卡是由模块e1000e驱动的。

钓鱼竿

现在我通过阅读代码发现了这一点。我确实对内核代码有所了解,所以我知道我应该去哪里找。但是,如果我不愿意,还有其他方法可以找到它——追踪。现在我不确定所有这些是否都适用于 2.6.32,但至少我在内核 3.2 上测试过它(差别不大)。我不会详细介绍如何配置您的内核以拥有所有这些功能。 Ubuntu 12.04 拥有所有需要的东西,如果您对 google 感兴趣 ftrace:

您需要 debugfs 安装和这样的脚本:

#!/bin/sh
DEBUGFS=`/sys/kernel/debug/`
echo $$ > $DEBUGFS/tracing/set_ftrace_pid
echo function > $DEBUGFS/tracing/current_tracer
exec $*

此脚本将 ftrace 设置为仅关心当前 PID,启用函数跟踪器并执行指定为参数的命令(不分叉,因为这会更改 PID)。

现在,如果您的应用程序正在使用此 ioctl /tmp/a.out,您可以调用:

~/bin/ftraceme.sh /tmp/a.out
echo -n "" > /sys/kernel/debug/tracing/current_tracer
grep ioctl /sys/kernel/debug/tracing/trace

就我而言,我有:

<...>-11009 [007] 596251.750675: sys_ioctl <-system_call_fastpath    (1)
<...>-11009 [007] 596251.750675: fget_light <-sys_ioctl
<...>-11009 [007] 596251.750675: security_file_ioctl <-sys_ioctl
<...>-11009 [007] 596251.750676: cap_file_ioctl <-security_file_ioctl
<...>-11009 [007] 596251.750676: do_vfs_ioctl <-sys_ioctl
<...>-11009 [007] 596251.750676: sock_ioctl <-do_vfs_ioctl           (2)
<...>-11009 [007] 596251.750677: sock_do_ioctl <-sock_ioctl          (3)
<...>-11009 [007] 596251.750677: inet_ioctl <-sock_do_ioctl          (4)
<...>-11009 [007] 596251.750677: udp_ioctl <-inet_ioctl
<...>-11009 [007] 596251.750678: dev_ioctl <-sock_do_ioctl           (5)
<...>-11009 [007] 596251.750678: _cond_resched <-dev_ioctl
<...>-11009 [007] 596251.750679: dev_load <-dev_ioctl
<...>-11009 [007] 596251.750680: rtnl_lock <-dev_ioctl
<...>-11009 [007] 596251.750680: dev_ethtool <-dev_ioctl             (6)
<...>-11009 [007] 596251.750684: rtnl_unlock <-dev_ioctl
<...>-11009 [007] 596251.750685: _cond_resched <-dev_ioctl

这证明了我上面写的。