在不修改内核的情况下拦截系统调用的最小开销方式

时间:2012-07-02 10:12:08

标签: c linux gcc x86-64 system-calls

我知道拦截系统调用的方法如下。

  1. 使用ptrace,但这似乎有很高的开销。根据我的知识,像strace这样的工具也在内部使用ptrace。
  2. 使用内核模块更改系统调用表,但据我所知,此方法在以后的Linux内核中不再可行。
  3. 使用LD_PRELOAD。但是,如果您直接进行系统调用而不使用某个包装库函数进行该系统调用,则无法使用此功能。
  4. 所以你看到上面提到的所有方法都有缺陷。所以我的问题是什么是在不修改内核的情况下拦截系统调用的方式,并且开销最小。

3 个答案:

答案 0 :(得分:4)

如果无法修改内核,则必须修改应用程序。您需要以某种方式拦截int / syscall / sysenter指令,方法是在那里设置断点(如果您可以在Linux中的应用程序中处理它们;您可以在Windows中使用SEH / VEH)或以更具侵入性的方式挂钩指令(将其更改为jmp到保存系统调用号和参数的代码,执行原始int / {{1} } / syscallsysenter返回)。

编辑:哦,我忘了补充说找到这些说明可能是一个挑战。您可能无法在已编译的二进制文件中正确识别它们。您可以错过一些(特别是在运行时创建的那些),您可以对jmp / int / syscall采取其他一些说明(如果您的代码分析不完美)。 OTOH,在运行时找到它们(通过在执行/模拟它们之前分析各个指令(或它们的块))将导致性能损失。

无论如何,性能问题很可能与正在进行的系统调用次数以及记录/跟踪信息量直接相关。如果你减少了(即只选择有趣的系统调用和参数)和/或只收集有关最后10000次系统调用的信息,并将数据保存在内存中并将其保存到文件中一次(最后应用程序),你会有更好的表现。

答案 1 :(得分:1)

使用动态检测框架,例如DTraceSystemTap。您的平台应该有一个或两个。

答案 2 :(得分:1)

Pintool也可能有所帮助;它也适用于Linux。