考虑一个创建子进程并在无限循环中打印信息的程序,在一秒后结束该进程:
输出结果为:
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
int main(void) {
pid_t pid = fork();
if (pid == 0) {
while (1)
puts("I'm still alive");
} else {
sleep(1);
puts("Dispatching...");
kill(pid, SIGTERM);
puts("Dispatched!");
}
return 0;
}
正如我所预期的那样,输出结果为:
I'm still alive
I'm still alive
...
Dispatching...
I'm still alive
I'm still alive
...
Dispatched!
这是有道理的,因为子进程在父进程发送信号后可能不会立即终止。
但是,一旦我通过管道运行程序或将输出重定向到另一个文件,例如
$ ./prog | tail -n 20
$ ./prog > out.txt
输出结果为:
I'm still alive
I'm still alive
...
Dispatching...
Dispatched!
也就是说,在父进程杀死子进程后,似乎没有来自子进程的输出。
这种差异的原因是什么?
stdout
是 tty,则在每个换行符上发生刷新,而在重定向输出时缓冲区刷新不那么频繁,特别是在仅打印两行的主进程的情况下,只有在其终止后才会发生刷新,因此所有子进程输出都会在此之前写入。 - Hartmut Holzgraefestdout
绑定到文件或管道时,它不是行缓冲的,父进程的输出只有在终止后才会被刷新,而子进程的输出则会在kill()
后立即被刷新。 - Avidan Borisov