2017-08-16 56 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?