Unix иерархия процессов - PullRequest
       9

Unix иерархия процессов

0 голосов
/ 30 апреля 2018

Нужно реализовать эту эту иерархию процессов

Каждый процесс, имеющий детей, не должен завершаться раньше, чем его дети. В термины сообщений, отображаемых функцией «info ()», сообщение END parent никогда не должен появляться перед сообщениями END своих детей. Функция информации выглядит следующим образом info(BEGIN | END, process_no, thread_no);

int main() {
    init();
    pid_t  pid2, pid3, pid4,pid5,pid6,pid7,pid8,pid9;
    info(BEGIN,1,0);

    pid2 = fork();
    if ( pid2 == 0 ) {
        // P2 child
        info(BEGIN,2,0);
        pid5 = fork();
        if ( pid5 == 0 ) {  // P5 child
            info(BEGIN,5,0);
            pid9 = fork();
            if(pid9 == 0){ // P9 child
                info(BEGIN,9,0);
                info(END,9,0);
            }
            waitpid(pid9,'\0','\0');
            info(END,5,0);
            // grandchild (of top-level parent)
        } else {
            waitpid(pid5,'\0','\0');
            info(END,2,0);
        }
    } else if((pid3 = fork()) == 0) {
        info(BEGIN,3,0); // P3 child
        pid4 = fork();
        if(pid4 == 0){ //P4 child
            info(BEGIN,4,0);
            info(END,4,0);
        }else{
            pid6 = fork();
            if(pid6 == 0){ //P6 child
                info(BEGIN,6,0);
                pid7 = fork();
                if(pid7 == 0){ //P7 child
                    info(BEGIN,7,0);
                    info(END,7,0);
                }
                waitpid(pid7,'\0','\0');
                info(END,6,0);
            }
        }
        waitpid(pid4,'\0','\0');
        waitpid(pid6,'\0','\0');
        info(END,3,0);
    }
    else{
        pid8=fork();
        if(pid8 == 0){ //P9 child
            info(BEGIN,8,0);
            info(END,8,0);
        }
        waitpid(pid2,'\0','\0');
        waitpid(pid3,'\0','\0');
        waitpid(pid4,'\0','\0');
        waitpid(pid5,'\0','\0');
        waitpid(pid6,'\0','\0');
        waitpid(pid7,'\0','\0');
        waitpid(pid8,'\0','\0');
        waitpid(pid9,'\0','\0');
        info(END, 1, 0);
    }

    for(int i=0; i<8; i++){ 
        wait(NULL);  
    }

    return 0;
}

Мой вывод

[ ] BEGIN P1 T0 pid=4370 ppid=4122 tid=1184286464
[ ] BEGIN P2 T0 pid=4371 ppid=4370 tid=1184286464
[ ] BEGIN P8 T0 pid=4373 ppid=4370 tid=1184286464
[ ] BEGIN P3 T0 pid=4372 ppid=4370 tid=1184286464
[ ]  END  P8 T0 pid=4373 ppid=4370 tid=1184286464
[ ] BEGIN P5 T0 pid=4374 ppid=4371 tid=1184286464
[ ]  END  P1 T0 pid=4373 ppid=4370 tid=1184286464
[ ] BEGIN P4 T0 pid=4375 ppid=4372 tid=1184286464
[ ] BEGIN P6 T0 pid=4376 ppid=4372 tid=1184286464
[ ]  END  P4 T0 pid=4375 ppid=4372 tid=1184286464
[ ] BEGIN P9 T0 pid=4377 ppid=4374 tid=1184286464
[ ]  END  P3 T0 pid=4375 ppid=4372 tid=1184286464
[ ]  END  P9 T0 pid=4377 ppid=4374 tid=1184286464
[ ] BEGIN P7 T0 pid=4378 ppid=4376 tid=1184286464
[ ]  END  P5 T0 pid=4377 ppid=4374 tid=1184286464
[ ]  END  P7 T0 pid=4378 ppid=4376 tid=1184286464
[ ]  END  P6 T0 pid=4378 ppid=4376 tid=1184286464
[ ]  END  P5 T0 pid=4374 ppid=4371 tid=1184286464
[ ]  END  P3 T0 pid=4378 ppid=4376 tid=1184286464
[ ]  END  P2 T0 pid=4371 ppid=4370 tid=1184286464
[ ]  END  P6 T0 pid=4376 ppid=4372 tid=1184286464
[ ]  END  P3 T0 pid=4376 ppid=4372 tid=1184286464
[ ]  END  P3 T0 pid=4372 ppid=4370 tid=1184286464
[ ]  END  P1 T0 pid=4370 ppid=4122 tid=1184286464

Ожидаемый результат:

[ ] BEGIN P1 T0 pid=4370 ppid=4122 tid=1184286464
[ ] BEGIN P2 T0 pid=4371 ppid=4370 tid=1184286464
[ ] BEGIN P3 T0 pid=4372 ppid=4370 tid=1184286464
[ ] BEGIN P8 T0 pid=4373 ppid=4370 tid=1184286464
[ ]  END  P8 T0 pid=4373 ppid=4370 tid=1184286464
[ ] BEGIN P4 T0 pid=4375 ppid=4372 tid=1184286464
[ ] BEGIN P5 T0 pid=4374 ppid=4371 tid=1184286464
[ ] BEGIN P6 T0 pid=4376 ppid=4372 tid=1184286464
[ ]  END  P4 T0 pid=4375 ppid=4372 tid=1184286464
[ ] BEGIN P9 T0 pid=4377 ppid=4374 tid=1184286464
[ ]  END  P9 T0 pid=4377 ppid=4374 tid=1184286464
[ ] BEGIN P7 T0 pid=4378 ppid=4376 tid=1184286464
[ ]  END  P5 T0 pid=4377 ppid=4374 tid=1184286464
[ ]  END  P7 T0 pid=4378 ppid=4376 tid=1184286464
[ ]  END  P6 T0 pid=4378 ppid=4376 tid=1184286464
[ ]  END  P3 T0 pid=4378 ppid=4376 tid=1184286464
[ ]  END  P2 T0 pid=4371 ppid=4370 tid=1184286464
[ ]  END  P1 T0 pid=4370 ppid=4122 tid=1184286464

Я пытаюсь разобраться в этом почти 2 часа, но не могу понять, что не так хорошо, я думаю, что это как-то связано с waitpid, но не могу понять ...

1 Ответ

0 голосов
/ 30 апреля 2018

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

Взять, к примеру, последнее предложение else. В этом блоке вы вызываете fork, чтобы создать pid8. Затем у вас есть процесс 8, печатающий BEGIN и END, но затем он не выходит из , он переходит к следующему коду, который, очевидно, предназначен для P1 (где он будет бессмысленно вызывать waitpid для процессов, которые это не создало). Но также он будет ошибаться при вызове info(END,1,0). То же самое происходит в нескольких других путях кода.

Несколько предложений:

  1. Вызывать waitpid в процессе можно только для тех процессов, которые созданы как прямые дочерние элементы. Это единственные, кому вы можете в любом случае успешно позвонить waitpid. Например, P1 не может ждать P4, который он не создал.

  2. Передайте NULL в качестве дополнительных аргументов waitpid , а не '\0'. (Последнее работает в большинстве реализаций C, потому что представление символа '\0' совпадает с представлением указателя NULL в этих реализациях, но это не правильно: вы должны передавать указатель на целое число [ или специальное значение NULL], а не char значение.)

  3. Проверьте статусы возврата на ваши системные вызовы. Если бы вы сделали это, вы бы увидели, что многие waitpid звонки не срабатывают. (На самом деле это не , вызывающее проблему в данном конкретном случае, но всегда полезно проверять и распечатывать сбои, поскольку они подскажут вам, почему программа не работает так, как вы ожидаете .)

  4. Самое главное, чтобы в каждом предложении if (pidX == 0) { после выполнения всего, что должен делать этот блок, поместите оператор exit(0), чтобы вызвать завершение процесса:

    pid8=fork();
    if(pid8 == 0){
        info(BEGIN,8,0);
        info(END,8,0);
        exit(0);          /* <<<<<<============ */
    }
    


Последнее предложение: Выберите стиль кодирования и придерживайтесь его. У вас есть

pid8=fork();
if(pid8 == 0){

и у вас есть

pid2 = fork();
if ( pid2 == 0 ) {

и у вас есть

if((pid3 = fork()) == 0) {

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

...