我在以下内容中没有确切找到有关以下内容的内容手册页。子进程中的假定行为是如何由本身产生的进程产生的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$