stdbuf 子进程的假定行为

stdbuf 子进程的假定行为

我在以下内容中没有确切找到有关以下内容的内容手册页。子进程中的假定行为是如何由本身产生的进程产生的stdbuf

例如:

stdbuf -oL myprog

来自代码,我知道它设置了LD_PRELOAD,据我所知,所有环境变量都会在任何子进程中继承。

fork();我对和子流程都感兴趣fork(); execv();。 (不确定这是否会有所作为。)

fork();根本不应该改变行为。execv()将使用相同的LD_PRELOAD(以及也存储在 env 中的 stdbuf 设置),从而应用相同的行为(来自示例:stdout 是行缓冲的)。

正确的?

答案1

strace(使用execve环境)和write系统调用可以帮助了解发生了什么:

这里使用stdbuf的是 GNU coreutils 8.25。我相信 FreeBSD 的stdbuf工作原理类似:

执行并且没有 fork:

$ env -i strace -s200 -vfe execve,write /usr/bin/stdbuf -o0 /usr/bin/env /usr/bin/env > /dev/null
execve("/usr/bin/stdbuf", ["/usr/bin/stdbuf", "-o0", "/usr/bin/env", "/usr/bin/env"], []) = 0
execve("/usr/bin/env", ["/usr/bin/env", "/usr/bin/env"], ["_STDBUF_O=0", "LD_PRELOAD=/usr/lib/x86_64-linux-gnu/coreutils/libstdbuf.so"]) = 0
execve("/usr/bin/env", ["/usr/bin/env"], ["_STDBUF_O=0", "LD_PRELOAD=/usr/lib/x86_64-linux-gnu/coreutils/libstdbuf.so"]) = 0
write(1, "_STDBUF_O=0\n", 12)           = 12
write(1, "LD_PRELOAD=/usr/lib/x86_64-linux-gnu/coreutils/libstdbuf.so\n", 60) = 60
+++ exited with 0 +++

LD_PRELOAD并且配置_STDBUF_O被传递给两个env命令。write()即使输出没有发送到终端,这两个系统调用也会确认输出没有被缓冲。

分叉并执行:

$ env -i strace -s200 -vfe execve,write /usr/bin/stdbuf -o0 /bin/sh -c '/usr/bin/env; :' > /dev/null
execve("/usr/bin/stdbuf", ["/usr/bin/stdbuf", "-o0", "/bin/sh", "-c", "/usr/bin/env; :"], []) = 0
execve("/bin/sh", ["/bin/sh", "-c", "/usr/bin/env; :"], ["_STDBUF_O=0", "LD_PRELOAD=/usr/lib/x86_64-linux-gnu/coreutils/libstdbuf.so"]) = 0
Process 16809 attached
[pid 16809] execve("/usr/bin/env", ["/usr/bin/env"], ["_STDBUF_O=0", "LD_PRELOAD=/usr/lib/x86_64-linux-gnu/coreutils/libstdbuf.so", "PWD=/home/stephane"]) = 0
[pid 16809] write(1, "_STDBUF_O=0\n", 12) = 12
[pid 16809] write(1, "LD_PRELOAD=/usr/lib/x86_64-linux-gnu/coreutils/libstdbuf.so\n", 60) = 60
[pid 16809] write(1, "PWD=/home/stephane\n", 19) = 19
[pid 16809] +++ exited with 0 +++
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED,

同样的情况。

所以 yes适用于它运行的命令及其所有后代(前提是它们不像动态链接器或 libc对 setuid/setgid... 应用程序所做stdbuf的那样清理环境)。LD_PRELOAD

答案2

缓冲是通过 fork/exec 继承的,timeout如以下测试代码所示:

bash-4.1$ cat isbuffed.c 
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void)
{
    printf("should not appear if buffered");
    sleep(999);
    exit(EXIT_SUCCESS);
}
bash-4.1$ make isbuffed
cc     isbuffed.c   -o isbuffed
bash-4.1$ timeout 3 ./isbuffed
bash-4.1$ stdbuf -o0 timeout 3 ./isbuffed
should not appear if bufferedbash-4.1$ 

相关内容