Проблема создания нескольких дочерних процессов - PullRequest
0 голосов
/ 24 сентября 2011

Я новичок в создании процессов и т. Д., Поэтому, вероятно, основной вопрос.
Я создаю фиксированное количество дочерних процессов, каждый из которых ничего не делает, кроме печати своего pid.Проблема в выводе, который я получаю.Посмотрите:

int main(){  
pid_t pid=0;  
int i=0,status=0;

    for(i=0;i<3;i++){
            pid=fork();
            switch(pid){
                    case 0:{        //Child
                            printf("\nChild pid: %d",getpid());
                            exit(0);
                            break;
                            }
                    case -1: {//Error
                            printf("Error occured in fork");
                            exit(1);
                            break;
                            }
                    default:{
                            printf("\nParent id: %d",getpid());
                            printf("\nIts child id: %d",pid);
                            wait(NULL);
                            }
            }

Вывод:
Child pid: 1450<br> Parent id: 1445<br> Its child id: 1450<br> Child pid: 1455Its child id: 1450<br> Parent id: 1445<br> Its child id: 1455<br> Child pid: 1460Its child id: 1455<br> Parent id: 1445<br> Its child id: 1460
Проблема в том, что я не знаю, почему появляется только второй оператор печати родительского процесса, а не первый, если таковой имеетсявсе.Я знаю, что не ожидаю завершения моих дочерних процессов (честно говоря, я не знаю, как бы я это сделал), но если родительский процесс выполняется до завершения своих дочерних процессов, почему не появляются оба его оператора печати и почему \nигнорируется и в этой строке.
Любая помощь будет принята с благодарностью.
Спасибо.

Обновление: если я заменю wait(NULL) на printf("\n%d\n",wait(NULL)) Это дает мне идеальный вывод без посторонних отпечатков.Есть идеи, что могло это исправить?Ведь они оба делают одно и то же.

Ответы [ 2 ]

1 голос
/ 24 сентября 2011

Проблема в том, что есть несколько процессов, одновременно записывающих в один и тот же файл (вашу консоль) без какого-либо контроля параллелизма или какой-либо блокировки. Это, и что эти странные существа, в лучшем случае, делают странные вещи, происходящие. Кроме того, помните, что printf буферизовано.

Ваш вывод должен читаться следующим образом:

Child pid: 1450    <- Child #1
Parent id: 1445    <- Parent #1.1
Its child id: 1450 <- Parent #1.2

Child pid: 1455[Its child id: 1450] <- Child #2 with garbage at the end
Parent id: 1445                     <- Parent #2.1
Its child id: 1455                  <- Parent #2.2

Child pid: 1460[Its child id: 1455] <- Child #3 with garbage at the end
Parent id: 1445                     <- Parent #3.2
Its child id: 1460                  <- Parent #3.2

Вы можете попробовать перенаправить вывод в файл и посмотреть, не имеет ли значение tty.

В любом случае, чтобы сделать это правильно, вам следует использовать любой механизм, который гарантирует многопроцессорную корректность.

UPDATE

Да, теперь я вижу это. У вас есть '\ n' в начале ваших строк печати, а не в конце, как обычно. Stdout обычно буферизуется строкой, это означает, что буфер сбрасывается на устройство, когда он видит '\ n'. И поскольку они у вас есть в начале, в буфере всегда есть одна строка, ожидающая вывода.

Теперь, когда вы fork обрабатываете свой процесс, выходной буфер дублируется, и последняя строка из родительского элемента печатается дочерним элементом (почему он печатается после , а не до, все еще остается загадкой). мне).

В любом случае, добавленный вами новый printf имеет в конце '\ n', поэтому он очищает буфер, fork находит его пустым и все идет хорошо. С таким же успехом можно позвонить fflush(stdout), но это громоздко.

Мораль истории такова: «Когда вы printf для целей отладки всегда ставьте \n в конце каждой строки, или вы можете получить частичное, смешанное содержимое.

0 голосов
/ 24 сентября 2011

Проблема заключается в буферизации и очистке стандартного вывода.

Обе строки печатаются, но не сбрасываются для вывода в ожидаемое время .... в зависимости от того, куда направляется вывод (файл,pipe, терминал, stderr и т. д.) printf использует разные стратегии буфера.

Я полагаю, что в вашем случае он только сбрасывает символы новой строки (отметьте man setbuf)

Переместите строку в конеца не в начале, например, ....

       printf("Parent id: %d\n",getpid());
       printf("Its child id: %d\n",pid);

И всегда следите за тем, чтобы \ n ставил в конце printf все ваши printfs.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...