我写了代码以按parent->g3->c2->g1->g2->c1
的顺序打印 pid 。
因此,我使用了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");
}
答案 0 :(得分:2)
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
)。
答案 1 :(得分:1)
我已使用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);
}
}
我没做过香糖。
我刚刚在{p>的开头添加了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)
,所以我将其删除。