fork执行顺序

时间:2011-03-04 19:18:19

标签: c linux posix scheduling fork

main()
{
if(!fork())
 while(1)
  printf("HELLO");
else
 while(1)
  printf("WORLD");

}

输出:...... HELLO HELLO HELLO ....等, 但执行应该是“RANDOM”,因为fork和parent进程是不同步的 我必须得到你好世界世界你好世界......(按照我预期的随机顺序) 但事实并非如此。 任何人都可以解释一下。

3 个答案:

答案 0 :(得分:4)

stdio是缓冲的,因此在填充缓冲区之前,任何进程都不会写入任何内容,然后将整个写入作为单个单元(对于普通文件通常是原子的,但不一定是终端设备,以及它是否是原子的管道是一个复杂的问题)。此外,如果您使用的是单核计算机,则一个进程将持续运行,直到内核认为它已经花费了足够的CPU时间,然后另一个进程将被安排等等。

如果您想让stdio缓冲问题消失,请在setbuf(stdout, 0);的开头添加main或使用stderr(默认情况下无缓冲)。

答案 1 :(得分:1)

好的,首先你没有得到HELLO和WORLDs的随机交错词,因为stdout被缓冲了。

因此,您的父级正在打印HELLO,直到该缓冲区变满,然后整个缓冲区最终会出现在您的屏幕上。孩子一样。

如果要同步此功能,可以使用2个管道在父母和孩子之间进行通信。 例如

  • 父母打印“HELLO”,
  • 孩子开始从pipe1读取。
  • parent将一个字符写入pipe1,表示孩子应该打印“WORLD”
  • 父母开始从pipe2读取
  • 孩子从pipe1读取,打印“WORLD”
  • child将一个字符写入pipe2,表示父级应该打印“HELLO”
  • 重复上述内容

-

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

void err(const char *error)
{
    perror(error);
    exit(1);
}

void run_handler(int readfd,int writefd,const char *message)
{
    for(;;) {
        char ch;
        int i;

        if((i = read(readfd,&ch,1)) == 0)
           break;
        else if(i < 0)
            err("read");

        //important: fflush the text so it ends up in the output
        //and not in an internal FILE* buffer.
        if(fputs(message,stdout) == EOF || fflush(stdout) == EOF) 
           break;

        if(write(writefd,&ch,1) != 1)
            err("write");
    }
}

int main()
{
    int pipe1[2];
    int pipe2[2];
    pid_t pid;

    if(pipe(pipe1) != 0)
        err("pipe1");
    if(pipe(pipe2) != 0)
        err("pipe2");

    if((pid = fork()) == 0 ) {
        //write one char to the parent to get it started
        char ch = '.';
        if(write(pipe1[1],&ch,1) != 1)
            err("write");
        //close the pipe ends we don't need
        close(pipe1[0]);
        close(pipe2[1]);

        run_handler(pipe2[0],pipe1[1],"WORLD\n");
    }else if(pid > 0) {
        //close the pipe ends we don't need
        close(pipe1[1]);
        close(pipe2[0]);
        run_handler(pipe1[0],pipe2[1],"HELLO ");
    } else {
       err("fork");
    }

    return 0;
}

答案 2 :(得分:0)

int main()
{
  if(!fork())
    while(1) {
      printf("HELLO");
      fflush(stdout);
    }
  else
    while(1) {
      printf("WORLD");
      fflush(stdout);
    }
}

使用它,然后printf的缓冲不会弄乱你的结果。