我有下面这段代码,我想解释一下在这段代码中fork()调用的行为,中断条件是作为命令行参数给出的。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
int i = 0;
char *ptr;
int x = strtol(argv[1], &ptr, 10);
while (fork())
{
if (i == x)
{
break;
}
printf("PID: %d, PPID: %d, i = %d\n", getpid(), getppid(), i++);
}
return 0;
}这是将1指定为命令行参数时的输出
PID: 684067, PPID: 14913, i = 0
PID: 684067, PPID: 14913, i = 0我认为应该执行一次fork()调用,创建子进程和父进程,向父进程返回一个非零的进程id,向子进程返回一个零的进程id。零值应该被解释为false,并且只有父进程会继续打印一次,然后将i的值递增到1,然后再次重复创建另一个子进程,这个子进程将再次不进入循环,这次作为i = 1,它将中断循环,那么为什么我看到打印的行是2行,而不是1行?I的较高值的输出更加令人费解,但不出所料地输出i*(i+3)/2 lines。有人能解释我假设中的缺陷吗?
发布于 2020-11-30 03:30:57
您看到的重复消息来自stdio buffer,以及printf实际上在缺省情况下并不打印的事实--它只是将一些内容放入一个缓冲区中,该缓冲区稍后会在缓冲区刷新时打印(如果不是在进程退出之前显式刷新或缓冲区填满,则会发生这种情况)。
最重要的是,当您派生一个子对象时,该子对象将获得所有父状态的副本--包括所有的stdio缓冲区。因此,如果stdio缓冲区中有任何未刷新的数据,它将被复制并(最终)写入两次--一次由父级写入,一次由子级写入。
您可以通过在printf后面放置一个显式的fflush(stdout);来避免这种情况。
更复杂的是,stdio还支持所谓的“行缓冲模式”,在这种模式下,每次写入新行时,它都会自动刷新文件。在一些系统上,这是缺省设置在stdout上的,但在其他系统上不是(它是由实现定义的)。您可以通过在主函数的开头使用setlinebuf(stdout);在标准输出上显式地设置行缓冲模式来利用这一点。
https://stackoverflow.com/questions/65064049
复制相似问题