Я проверил этот код с 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)
, поэтому я удалил его.