哪个驱动程序正在处理我的 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
这证明了我上面写的。
我正在打开这样的套接字:
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
这证明了我上面写的。