2017-08-16 110 views
0

当我在gdb中运行时,父进程在waitpid处挂起,我不知道为什么。父母应该从argv获取参数并通过管道将其发送给孩子。然后,父母应该通过返回来接收来自孩子的参数的总和。不知道为什么它这样做。父进程在调用waitpid后挂起

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <sys/wait.h> 
#include <sys/poll.h> 

static int myPipe[2]; 

int main(int argc, char **argv) 
{ 
    pid_t pid; 
    int value; 
    int status; 
    // set up pipe 

    if(pipe(myPipe)) 
    { 
     printf("pipe error\n"); 
     return -1; 
    } 

    // call fork() 
    printf("CS201 - Assignment 3 Premium - I. Forgot\n"); 
    pid = fork(); 
    if (pid == 0) { 
     // -- running in child process -- 
     int  sum = 0; 
     close(myPipe[1]); 

     for(int i = argc; i > 1; i--) 
     { 
      read(myPipe[0], &value, sizeof(value)); 
      sum += value; 
     } 

     // Return sum of numbers. 
     return sum; 
     } 
    else { 
     // -- running in parent process -- 
     int sum = 0; 
     close(myPipe[0]); 

for(int i = argc; i > 1; i--) 
     { 
      value = atoi(argv[i-1]); 
      write(myPipe[0], &value, sizeof(value)); 
     } 
     waitpid(pid, &status, 0); 
     sum = status; 

     printf("sum = %d\n", sum); 
     return 0; 
     } 

回答

1

您的问题是,在父,你仔细密切myPipe[0],然后神秘地决定写信给它,而不是依然敞开myPipe[1]的。如果你错误地检查了你的系统调用,你会知道你没有发送任何数据给孩子。实际上,孩子仍然在等待数据到达,并且不会退出,并且父母正在等待不会退出的孩子退出,因此您会陷入僵局。

我使用stderr.cstderr.h的错误报告功能--GitHub(https://github.com/jleffler/soq/tree/master/src/libsoq)提供的代码报告错误(和进度)。

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <sys/wait.h> 
#include "stderr.h" 

static int myPipe[2]; 

int main(int argc, char **argv) 
{ 
    pid_t pid; 
    int value; 
    int status; 
    err_setarg0(argv[0]); 
    err_setlogopts(ERR_PID|ERR_MICRO); 

    if (pipe(myPipe) != 0) 
     err_syserr("pipe failed: "); 

    // call fork() 
    printf("CS201 - Assignment 3 Premium - I. Forgot\n"); 
    pid = fork(); 
    if (pid < 0) 
     err_syserr("fork failed: "); 
    else if (pid == 0) 
    { 
     // -- running in child process -- 
     int sum = 0; 
     if (close(myPipe[1]) != 0) 
      err_syserr("failed to close write end of pipe in child: "); 

     for (int i = argc; i > 1; i--) 
     { 
      if (read(myPipe[0], &value, sizeof(value)) != sizeof(value)) 
       err_syserr("failed to read from parent: "); 
      sum += value; 
     } 
     if (close(myPipe[0]) != 0) 
      err_syserr("failed to close read end of pipe in child: "); 

     err_remark("Exiting: sum = %d\n", sum); 
     return sum; 
    } 
    else 
    { 
     // -- running in parent process -- 
     int sum = 0; 
     close(myPipe[0]); 

     for (int i = argc; i > 1; i--) 
     { 
      value = atoi(argv[i - 1]); 
      err_remark("Writing: %d\n", value); 
      if (write(myPipe[1], &value, sizeof(value)) != sizeof(value)) 
       err_syserr("failed to write to child: "); 
     } 
     if (waitpid(pid, &status, 0) != pid) 
      err_syserr("failed to wait for child %d: ", pid); 
     sum = status; 

     printf("sum = %d\n", sum); 
     if (WIFEXITED(status)) 
      printf("exit status: %d\n", WEXITSTATUS(status)); 
     return 0; 
    } 
} 

和示例输出(在fp71.c源代码,程序fp71):

$ gcc -O3 -g -I./inc -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes \ 
>  -Wstrict-prototypes fp71.c -o fp71 -L./lib -lsoq 
$ fp71 1 2 4 7 
CS201 - Assignment 3 Premium - I. Forgot 
fp71: 2017-08-15 20:11:48.453688 - pid=86097: Writing: 7 
fp71: 2017-08-15 20:11:48.454267 - pid=86097: Writing: 4 
fp71: 2017-08-15 20:11:48.454275 - pid=86097: Writing: 2 
fp71: 2017-08-15 20:11:48.454281 - pid=86097: Writing: 1 
fp71: 2017-08-15 20:11:48.454348 - pid=86098: Exiting: sum = 14 
sum = 3584 
exit status: 14 
$ 

十进制值3584对应于十六进制0x0E00。如果你分析WIFEXITED()WEXITSTATUS,那么就等于你所期望的14。 (另见Exit values bigger than 255 — possible?