ошибка ошибки waitpid () - PullRequest
0 голосов
/ 07 октября 2018

Я написал код для печати pid в порядке parent->g3->c2->g1->g2->c1.

Поэтому я использовал wait() и waitpid().Но я потерпел неудачу.

Поэтому я написал "готовый" код, чтобы узнать, в чем проблема.

И я знал, что c1 игнорирует waitpid и печатает what-> finish.

Как я могу решить эту проблему


#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>

void main()
{
pid_t c1,c2,g1,g2,g3;

printf("parent:%d\n", (int)getpid());
c1=fork();
int status;
if (c1>0) {
        c2=fork();
        if (c2==0) {
            g3=fork();
            if (g3==0) {
                    printf("g3:%d\n",(int)getpid());
            } else if (g3>0) {
            wait(&status);
            printf("c2:%d\n",(int)getpid());
            }
       }
} else if (c1==0) {
        waitpid(c2,&status,WUNTRACED);
    printf("what\n");
    g1=fork();
    if (g1>0) {
            g2=fork();
            if (g2==0) {
                printf("g2:%d\n",(int)getpid());
            } else if (g2>0) {
                    waitpid(g1,&status,WUNTRACED);
                    printf("c1:%d\n", (int)getpid());
            }
        } else if (g1==0) {
            waitpid(g2,&status,WUNTRACED);
            printf("g1:%d\n",(int)getpid());
            } else {
                printf("failed\n");
                exit(1);
            }
} else {
    printf("main failed\n");
    exit(1);
} printf("finish\n");
}

enter image description here

Ответы [ 2 ]

0 голосов
/ 07 октября 2018
pid_t c1,c2,g1,g2,g3;

printf("parent:%d\n", (int)getpid());
c1=fork();
int status;
if (c1>0) {
     ....
} else if (c1==0) {
        waitpid(c2,&status,WUNTRACED);

переменная c2 никогда не задавалась, поэтому она может содержать любой мусор, который оказался в стеке.Компилятор предупредит вас об этом, если вы запустите его с флагом -Wall.

Также вы должны всегда проверить возвращаемое значение waitpid;это также поймало бы ошибку.

И после fork не предполагайте, что дочерний элемент будет запланирован для запуска до родителя или наоборот.

    printf("what\n");
    g1=fork();
    if (g1>0) {
            ...
        } else if (g1==0) {
            waitpid(g2,&status,WUNTRACED);

То же, что и выше, переменная g2 используется без инициализации.

Кроме того, возвращаемое значение main должно быть int, а не void.

И вы всегда должны компилировать с включенными флагами -O2 -Wextra -Wall, что избавит вас от многих проблем.Если вы найдете некоторые предупреждения излишними, вы можете отключить их по отдельности;например.(-Wno-parentheses, -Wno-unused).

0 голосов
/ 07 октября 2018

Я проверил этот код с gcc 6.3.0, и он там работает правильно.Ну, этот код печатает их в том порядке, в котором вы спросили:

#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/types.h>

static int *glob_var;

int main()
{
int c1,c2,g1,g2,g3;
glob_var = mmap(NULL, sizeof *glob_var, PROT_READ | PROT_WRITE, 
                MAP_SHARED | MAP_ANONYMOUS, -1, 0);
printf("parent:%d\n", (int)getpid());
*glob_var = 0;
c1=fork();
int status;
if (c1>0) {
        c2=fork();
        if (c2==0) {
            g3=fork();
            if (g3==0) {
                printf("g3:%d\n",(int)getpid());
            } else if (g3>0) {
            wait(&status);
            printf("c2:%d\n",(int)getpid());
            *glob_var = 1;
            }
   }
} else if (c1==0) {
       while(*glob_var == 0);

    printf("what\n");
    g1=fork();
    if (g1>0) {
        waitpid(g1,&status,WUNTRACED);
        g2=fork();

        if (g2==0) {

            printf("g2:%d\n",(int)getpid());
        } else if (g2>0) {
                waitpid(g2,&status,WUNTRACED);
                printf("c1:%d\n", (int)getpid());
        }
    } else if (g1==0) {

        printf("g1:%d\n",(int)getpid());
        } else {
            printf("failed\n");
            exit(1);
        }
} else {
    printf("main failed\n");
    exit(1);
}

}

Я сделал несколько ошибок.

Я только добавил waitpid(g2,&status,WUNTRACED); в начале

 else if (g2>0) {
            waitpid(g2,&status,WUNTRACED);
            printf("c1:%d\n", (int)getpid());
    } 

условный оператор, поэтому g2 будет завершен до c1.

И waitpid(g1,&status,WUNTRACED); добавлен в условный оператор if(g1>0), поэтому g1 будет завершен до g2.

А также я использовал glob_var, которая является глобальной переменной, объявленной как static int *glob_var; и используемой mmap для разделения ее между родителем и дочерним элементом.

 glob_var = mmap(NULL, sizeof *glob_var, PROT_READ | PROT_WRITE, 
            MAP_SHARED | MAP_ANONYMOUS, -1, 0);

И использовавшей ее как семафор для выполнения c2 перед c1 ион работает так же, как когда c2 будет завершен, он изменит значение семафора с 0 на 1 , и после этого только цикл while(*glob_var == 0) прервется, else if(c1==0) условие продолжится.

И также нет необходимости в waitpid(c2,&status,WUNTRACED); в else if (c1==0), поэтому я удалил его.

...