порядок исполнения форка - PullRequest
0 голосов
/ 04 марта 2011
main()
{
if(!fork())
 while(1)
  printf("HELLO");
else
 while(1)
  printf("WORLD");

}

вывод: ... Привет Привет Привет .... и т. Д., Но выполнение должно быть "RANDOM" , потому что процесс fork и parent несинхронизирован и я ДОЛЖЕН ПОЛУЧИТЬ КАК ПРИВЕТСТВЕННЫЙ МИР ПРИВЕТСТВЕННЫЙ МИР ... (что-то в случайном порядке, чего я и ожидал) Но этого не произошло. Может ли кто-нибудь объяснить.

Ответы [ 3 ]

4 голосов
/ 04 марта 2011

stdio буферизуется, поэтому ни один из процессов не будет писать ничего, пока буфер не будет заполнен, а затем сделает всю запись как единый блок (который обычно является атомарным для обычных файлов, но не обязательно для терминальных устройств, и является ли он атомарным для труб это сложное дело). Кроме того, если вы работаете на одноядерном компьютере, один процесс будет работать непрерывно до тех пор, пока ядро ​​не сочтет, что оно потратило достаточно времени на процессор, тогда другой будет запланирован и т. Д.

Если вы хотите устранить проблему буферизации stdio, добавьте setbuf(stdout, 0); в начале main или используйте stderr (по умолчанию небуферизованный).

1 голос
/ 04 марта 2011

Хорошо, во-первых, вы не получаете всего случайного запутанного слова HELLO и WORLD, потому что stdout буферизован.

Итак, ваш родитель печатает ПРИВЕТ, пока этот буфер не заполнится, а затем весь этот буфер не окажется на вашем экране. То же самое для ребенка.

Если вы хотите синхронизировать это, вы можете использовать 2 канала для связи между вашим родителем и ребенком. например

  • родительские принты "HELLO",
  • ребенок начинает читать с трубы1.
  • parent пишет символ в pipe1, чтобы сигнализировать, что потомок должен вывести «WORLD»
  • родитель начинает чтение с канала2
  • ребенок читает из pipe1, печатает "МИР"
  • 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;
}
0 голосов
/ 04 марта 2011
int main()
{
  if(!fork())
    while(1) {
      printf("HELLO");
      fflush(stdout);
    }
  else
    while(1) {
      printf("WORLD");
      fflush(stdout);
    }
}

Используйте это, тогда буферизация printf не испортит ваши результаты.

...