Fork() 未在父进程中返回 id > 0
Fork() is not returning an id > 0 in the parent process
我目前正在尝试了解 fork() 和一般流程。
我的任务是执行 fork() 一定次数 - n - 用户可以输入。另外,我应该使用 waitpid() 来等待我的进程终止。每个进程都应该 return 一个介于 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 中调用它吗?
此外,一旦最后一次迭代结束并到达 return,我就会收到分段错误(核心转储)错误。
我现在迷路了。我不太明白我的错误在哪里。
您没有得到 parent 案例的任何输出,因为 parent 进程 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
中的 return 值不应按原样使用。您需要使用 WIF
宏来确定 child 存在状态,然后使用 WEXITSTATUS
宏来获取 return 值。这是手册页中的示例:
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");
}
int *returnvalue;
这只是一个指向 int
的 指针 ,但指向未定义的位置,因此:
waitingID = waitpid(pid, returnvalue, 0);
会将状态代码写入某个可能不属于您的进程的随机内存位置(根据c,通过未初始化的指针写入是未定义的行为)。
简单的事情,而不是定义一个指针,定义一个实际的 int
变量:
int returnvalue;
并传递指向该变量的指针:
waitingID = waitpid(pid, &returnvalue, 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);
我目前正在尝试了解 fork() 和一般流程。
我的任务是执行 fork() 一定次数 - n - 用户可以输入。另外,我应该使用 waitpid() 来等待我的进程终止。每个进程都应该 return 一个介于 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 中调用它吗?
此外,一旦最后一次迭代结束并到达 return,我就会收到分段错误(核心转储)错误。
我现在迷路了。我不太明白我的错误在哪里。
您没有得到 parent 案例的任何输出,因为 parent 进程 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
中的 return 值不应按原样使用。您需要使用 WIF
宏来确定 child 存在状态,然后使用 WEXITSTATUS
宏来获取 return 值。这是手册页中的示例:
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");
}
int *returnvalue;
这只是一个指向 int
的 指针 ,但指向未定义的位置,因此:
waitingID = waitpid(pid, returnvalue, 0);
会将状态代码写入某个可能不属于您的进程的随机内存位置(根据c,通过未初始化的指针写入是未定义的行为)。
简单的事情,而不是定义一个指针,定义一个实际的 int
变量:
int returnvalue;
并传递指向该变量的指针:
waitingID = waitpid(pid, &returnvalue, 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);