为什么_do_fork()的kretprobe只返回一次?

时间:2017-04-07 12:04:38

标签: c linux kernel systemtap kprobe

当我用fork编写一个小脚本时,syscall返回两次进程(每个进程一次):

#include <stdio.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
    int pid = fork();

    if (pid == 0) {
        // child
    } else if (pid > 0) {
        // parent
    }
}

如果我使用systemtap进行检测,我只找到一个返回值:

// fork() in libc calls clone on Linux
probe syscall.clone.return {
    printf("Return from clone\n")
}

SystemTap installes probes on _do_fork而不是克隆,但不应该改变任何东西。)

这让我很困惑。几个相关的问题:

  • 为什么系统调用只返回一次?
  • 如果我正确理解_do_fork code,则会在函数中间克隆进程。 (copy_processwake_up_new_task)。不应该在两个进程中运行后续代码吗?
  • 系统调用之后的内核代码是否与系统调用之前的用户代码在同一个线程/进程中运行?

1 个答案:

答案 0 :(得分:4)

  1. 创建孩子可能会失败,因此必须检测和处理错误
  2. 孩子有不同的回报值,这也必须处理
  3. 可能是父母有清理/要做的其他行动
  4. 因此,代码必须区分执行父项和子项。但是没有关于排序的检查,这已经强烈暗示孩子首先不执行此代码。因此,应该寻找新孩子回归的专门场所。

    由于代码非常庞大和毛茸茸,人们可以尝试作弊,只是寻找&#39; fork&#39;在特定于arch的代码中,它可以快速显示ret_from_fork。

    通过 - &gt;设定起点。 do_fork - &gt; copy_process - &gt; copy_thread_tls http://lxr.free-electrons.com/source/arch/x86/kernel/process_64.c#L158

    因此

      

    为什么系统调用只返回一次?

    它不会返回一次。有2个返回线程,除了另一个使用不同的代码路径。由于探头仅安装在第一个探头上,因此您无法看到另一个探头。另见下文。

      

    如果我正确理解了_do_fork代码,则会在函数中间克隆该进程。 (copy_process和wake_up_new_task)。不应该在两个进程中运行后续代码吗?

    我之前注意到这是错误的。真正的问题是让孩子与父母一起回归的好处是什么。我没有看到任何它会很麻烦(额外的特殊外壳,如上所述)。要重新声明:让孩子返回 elsehwere 让呼叫者不必处理返回的孩子。他们只需要检查错误。

      

    系统调用之后的内核代码是否与系统调用之前的用户代码在同一个线程/进程中运行?

    系统调用后的内核代码是什么?如果你是线程X并进入内核,你仍然是线程X。