【发布时间】:2011-01-11 08:45:08
【问题描述】:
我正在使用 Linux 安全模块挂钩向 recv() 系统调用添加一些自定义功能。与原始的 recv() 相比,我想测量此功能的开销。我编写了一个简单的 tcp 服务器,可以在有和没有模块的情况下运行。此 tcp 服务器调用 recv() 函数“N”次。它测量每个 recv 所花费的时间,例如:
clock_gettime(before);
recv()
clock_gettime(after);
global_time += after - before.
最后,我用“global_time/N”打印单个recv() 的平均时间。让我们将此时间称为“user_space_avg_recv”时间。
在我的模块中,我想放置时间测量函数来计算我的钩子的确切执行时间。我尝试了 3 种方法。
-
我使用 jiffies 如下:
sj = jiffies; my_hook(); ej = jiffies; current->total_oh = ej - sj;但我发现 sj 和 ej 值之间没有区别。因此 total_oh 没有改变。
我使用 current_kernel_time() 因为我认为它以纳秒为单位返回时间。但是,再一次,前后时间没有区别。
我使用了 get_cycles。我打印进程退出时的总周期。但是,当我将总周期值转换为毫秒时,它会远大于 “user_space_avg_recv”值。这没有意义,因为内核内部的测量值总是小于从用户空间测量的时间值。这可能意味着我要么没有使用正确的 API 进行测量,要么在将值从周期转换为毫秒时出错。
我基本上使用以下公式将周期转换为毫秒:
avg overhead of my hook in milliseconds =
(((cycles / 2.99) / 10^6) / N)
2.99 因为我的时钟频率是 2.99Ghz
几点:
我的用户空间程序使用 set affinity 绑定到单个内核。
我使用的是内核 2.6.22.14
为了阻止内核在我的钩子中切换上下文,我使用了 preempt_disable() 和 preempt_enable()。因此它不会计算其他内核线程的执行时间。即使这样,由于我的钩子使用了一些 I/O,我的线程可能会自愿释放控制,或者可能会发生一些中断,这可能会增加总周期数。
问题: 如何在内核中准确测量函数执行时间?
【问题讨论】:
-
尝试在 BIOS 中禁用频率更改并按周期重新测量
-
你试过ktime_get吗?
标签: linux-kernel