Fork()没有返回id>父进程中为0

时间:2015-09-20 10:44:21

标签: c unix fork

我目前正在尝试了解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)错误。

我现在迷路了。我无法弄清楚我的错误在哪里。

3 个答案:

答案 0 :(得分:3)

int *returnvalue;

这只是{em>指针到int,但指向未定义,所以这个:

waitingID = waitpid(pid, returnvalue, 0);

会将状态代码写入某个可能不属于您的进程的随机内存位置(就而言,通过未初始化的指针写入未定义的行为)。

简单的事情是,而不是定义指针​​,定义一个实际的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);