【问题标题】:Interpreting STRACE output - pipes and forks解释 STRACE 输出 - 管道和分叉
【发布时间】:2015-04-30 07:16:59
【问题描述】:

我有以下用 C 语言编写的代码,取自 https://beej.us/guide/bgipc/html/multi/pipes.html

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

int main(void)
{ 
    int pfds[2];

    pipe(pfds);

    if (!fork()) {
        close(1);       /* close normal stdout */
        dup(pfds[1]);   /* make stdout same as pfds[1] */
        close(pfds[0]); /* we don't need this */
        execlp("/bin/ls", "ls", NULL);
    } else {
        close(0);       /* close normal stdin */
        dup(pfds[0]);   /* make stdin same as pfds[0] */
        close(pfds[1]); /* we don't need this */
        execlp("/usr/bin/wc", "wc", "-l", NULL);
    }

return 0;
}

使用 strace 在终端中编译和运行此代码时,我得到以下输出:

execve("./forks", ["./forks"], [/* 55 vars */]) = 0
arch_prctl(ARCH_SET_FS, 0x7f2b0e498700) = 0
pipe([3, 4])                            = 0
clone(Process 7304 attached
child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f2b0e4989d0) = 7304
[pid  7303] execve("/usr/bin/wc", ["wc", "-l"], [/* 55 vars */] <unfinished ...>
[pid  7304] execve("/bin/ls", ["ls"], [/* 55 vars */] <unfinished ...>
[pid  7303] <... execve resumed> )      = 0
[pid  7304] <... execve resumed> )      = 0
[pid  7303] arch_prctl(ARCH_SET_FS, 0x7f558acde700) = 0
[pid  7304] arch_prctl(ARCH_SET_FS, 0x7f4bef4f67c0) = 0
[pid  7304] exit_group(0)               = ?
Process 7304 detached
--- SIGCHLD (Child exited) @ 0 (0) ---
21
exit_group(0) 

谁能逐行解释 strace 输出中发生了什么?我试图研究如何解释 strace 输出,但没有任何运气。

提前致谢。

【问题讨论】:

    标签: c linux pipe fork strace


    【解决方案1】:
    execve("./forks", ["./forks"], [/* 55 vars */]) = 0
    

    shell 使用您的可执行文件调用execve,并将./forks 调用为argv[0]/* 55 vars */ 是继承自 shell 的环境变量。

    arch_prctl(ARCH_SET_FS, 0x7f2b0e498700) = 0
    

    可能为新启动的进程设置线程本地存储。

    pipe([3, 4])
    

    pipe 系统调用返回一对描述符,34。这些数字是这样的,因为到目前为止,除了 0 (stdin)、1 (stdout) 和 2 (stderr) 之外,没有为进程分配任何描述符。

    clone(Process 7304 attached child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f2b0e4989d0) = 7304
    

    clone 系统调用对应于对fork 的调用,产生一个新进程。尽管 fork 通常被称为系统调用,特别是在 Linux 上,它封装了对 clone(2) 的调用。

    [pid  7303] execve("/usr/bin/wc", ["wc", "-l"], [/* 55 vars */] <unfinished ...>
    [pid  7304] execve("/bin/ls", ["ls"], [/* 55 vars */] <unfinished ...>
    [pid  7303] <... execve resumed> )      = 0
    [pid  7304] <... execve resumed> )      = 0
    [pid  7303] arch_prctl(ARCH_SET_FS, 0x7f558acde700) = 0
    [pid  7304] arch_prctl(ARCH_SET_FS, 0x7f4bef4f67c0) = 0
    [pid  7304] exit_group(0)
    

    在父进程和子进程中,启动了两个新的可执行文件。子进程以[pid 7304] exit_group(0) 退出,父进程立即收到SIGCHLD 信号,表明子进程已更改其状态。

    【讨论】:

    • 太棒了,非常感谢。快来看看,ls 和 wc 命令到底在哪里执行的?
    • ls 在子进程 (pid 7304) 中执行,wc 在父进程 (pid 7303) 中执行。
    • 所以[pid 7303] execve("/usr/bin/wc", ["wc", "-l"], [/* 55 vars */] &lt;unfinished ...&gt; 行是父级执行的位置? @blagovestbuyukliev
    • 关于execve 的基本理解是它会启动一个新进程来代替调用进程,但不会改变它的pid,因此调用后进程层次结构保持不变。自您的程序启动以来,Pid 7303 就存在。
    • “-f”选项告诉 strace 遵循子进程(适用于“大多数”情况)。
    猜你喜欢
    • 2021-07-26
    • 2023-03-18
    • 2011-09-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-17
    相关资源
    最近更新 更多