我目前正在尝试了解fork()和流程。
我的任务是执行fork()一定次数 - n - 用户可以输入。另外,我应该使用waitpid()等待我的进程终止。每个进程都应该返回1到6之间的随机数。
到目前为止,这是我的代码:
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
int main(){
int n,i;
int *returnvalue;
int pid;
int waitingID;
time_t t;
srand((unsigned)time(&t));
printf("How many processes to start?\n");
scanf("%d",&n);
for(i=0; i < n; i++){
pid = fork();
if(pid==0){
printf("I am %d, from iteration %d\n",getpid(), i);
}
else if(pid > 0){
waitingID = waitpid(pid, returnvalue, 0);
printf("Return-value of %d is: %d\n", waitingID, *returnvalue);
}
else{
printf("A problem occured.");
}
}
return rand()%6;
}
以下是当前程序的示例输出:
How many processes to start?
5
I am 6449, from iteration 0
I am 6450, from iteration 1
I am 6451, from iteration 2
I am 6452, from iteration 3
I am 6453, from iteration 4
Segmentation fault (core dumped)
如您所见,我遇到了一些问题:
根本没有调用else if (pid>0)
。因此不会发生等待。对于相应的父进程,不应该在每个fork中调用它吗?
此外,一旦最后一次迭代结束并返回,我就会收到Segmentation fault(core dumped)错误。
我现在迷路了。我无法弄清楚我的错误在哪里。
答案 0 :(得分:3)
int *returnvalue;
这只是{em>指针到int
,但指向未定义,所以这个:
waitingID = waitpid(pid, returnvalue, 0);
会将状态代码写入某个可能不属于您的进程的随机内存位置(就c而言,通过未初始化的指针写入未定义的行为)。
简单的事情是,而不是定义指针,定义一个实际的int
变量:
int returnvalue;
并传递指向该变量的指针:
waitingID = waitpid(pid, &returnvalue, 0);
答案 1 :(得分:1)
您无法获得父案例的任何输出,因为父流程waitpid
导致了细分错误。 returnvalue
是任何未初始化的指针。你需要这样做:
int returnvalue;
...
pid = fork();
if(pid==0){
printf("I am %d, from iteration %d\n",getpid(), i);
}
else if(pid > 0){
waitingID = waitpid(pid, &returnvalue, 0);
printf("Return-value of %d is: %d\n", waitingID, returnvalue);
}
但即便如此,也不是你想要的。 waitpid
的返回值不应按原样使用。您需要使用WIF
宏来确定子存在状态,然后使用WEXITSTATUS
宏来获取返回值。这是手册页中的示例:
if (WIFEXITED(status)) {
printf("exited, status=%d\n", WEXITSTATUS(status));
} else if (WIFSIGNALED(status)) {
printf("killed by signal %d\n", WTERMSIG(status));
} else if (WIFSTOPPED(status)) {
printf("stopped by signal %d\n", WSTOPSIG(status));
} else if (WIFCONTINUED(status)) {
printf("continued\n");
}
答案 2 :(得分:0)
函数waitpid
尝试写入returnvalue
指向的存储。在您的代码returnvalue
尚未初始化,因此
它的价值是未定义的。
由于waitpid
正在尝试写入未知地址,因此导致崩溃。
根据其他人的建议,缓解此问题的一种方法是使用int returnvalue
,然后将其地址&returnvalue
传递给waitpid
。
这样,因为变量returnvalue
是在堆栈上创建的,所以它的地址定义良好,waitpid
也可以写入它。
你可以做的另一个值是,虽然效率不高是调用malloc
并给你的指针一个地址(存储将在堆上创建而不是堆栈),这样你就可以了然后可以将其传递给waitpid
。但是不要忘记之后再打电话给free
。
returnvalue = malloc(sizeof(int));
waitingID = waitpid(pid, returnvalue, 0);
printf("Return-value of %d is: %d\n", waitingID, *returnvalue);
free(returnvalue);