2011-07-29 522 views
1

我正在嘗試編寫生成兩個子進程的代碼,這兩個子進程通過管道相互發送消息,然後終止。但是,當我運行下面的代碼時,只有child2打印它的問候語,但是child1仍然打印它從child2獲得的消息,其中child1沒有。兩個子進程與管道之間進行通信

有沒有人知道我的方法有什麼問題?

#include <string.h> 
#include <stdlib.h> 
#include <stdio.h> 
#include <sys/types.h> 
#include <unistd.h> 

int main(int argc, char** argv) { 
    char chld_1_send[20] = "hello from child 1"; 
    char chld_1_recv[20]; 
    char chld_2_send[20] = "hi from child 2"; 
    char chld_2_recv[20]; 

    int chld_1_outgoing[2]; 
    int chld_2_outgoing[2]; 

    pipe(chld_1_outgoing); 
    pipe(chld_2_outgoing); 

    int chld_1_status, chld_2_status; 
    pid_t chld_1, chld_2; 

    chld_1 = fork(); 

    if(chld_1 == 0) { 
     chld_2 = fork(); 
    } 

    if(chld_1 == 0 && chld_2 == 0) { 
     printf("parent [pid:%d] waiting on both children to finish\n", getpid()); 

     while(wait(&chld_1_status) != chld_1 && wait(&chld_2_status) != chld_2) {} 

     printf("done waiting\n"); 
    } 
    else if(chld_1 != 0 && chld_2 == 0) { 
     printf("this is child 1 [pid:%d] with parent [pid:%d]\n", getpid(), getppid()); 

     write(chld_1_outgoing[1], chld_1_send, strlen(chld_1_send)); 
     while(read(chld_1_outgoing[0], &chld_1_recv, sizeof(chld_2_recv)) < 0) {} 

     printf("child 2 said '%s'\n", chld_1_recv); 
     exit(0); 
    } 
    else if(chld_2 != 0 && chld_1 == 0) { 
     printf("this is child 2 [pid:%d] with parent [pid:%d]\n", getpid(), getppid()); 

     write(chld_2_outgoing[1], chld_2_send, strlen(chld_2_send)); 
     while(read(chld_2_outgoing[0], &chld_2_recv, sizeof(chld_2_recv)) < 0) {} 

     printf("child 1 said '%s'\n", chld_2_recv); 

     exit(0); 
    } 

    printf("both children have terminated successfully\n"); 

    return 0; 
} 

然而,運行此命令打印出該終端和進入一個無限循環:

$ this is child 2 [pid:15713] with parent [pid:1] 
child 1 said 'hi from child 2' 
parent [pid:15714] waiting on both children to finish 
+0

http://developers.sun.com/solaris/articles/named_pipes.html – Anders

+0

是否有沒有命名管道做到這一點?我的意思是一個管道仍然能夠與另一個溝通,而不是另一個孩子出於某種原因。 – David

+0

我改變了waitpid調用等待。但是,現在該程序進入無限循環。 – David

回答

2

下面是一個簡單的例子,這肯定可以改善,但應該讓你開始。 還有關於Link1Link2的更多信息。

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

/* max receiving buffer size; Note: no check or enforcement is made on this value*/ 
#define BUF_SIZE 256 

int main() 
{ 
    int pfd1[2]; 
    int pfd2[2]; 

    ssize_t numRead = -1; 
    /* Note: working under the assumption that the messages 
     are of equal length*/ 
    const char* messageOne = "Hello from child ONE.\n"; 
    const char* messageTwo = "Hello from child TWO.\n"; 

    const unsigned int commLen = strlen(messageOne) + 1; 

    char buf[BUF_SIZE]; 

    if (pipe(pfd1) == -1) 
    { 
     printf("Error opening pipe 1!\n"); 
     exit(1); 
    } 

    if (pipe(pfd2) == -1) 
    { 
     printf("Error opening pipe 2!\n"); 
     exit(1); 
    } 

    printf("Piped opened with success. Forking ...\n"); 

    // child 1 
    switch (fork()) 
    { 
     case -1: 
      printf("Error forking child 1!\n"); 
      exit(1); 

     case 0: 
      printf("\nChild 1 executing...\n"); 
      /* close reading end of first pipe */ 
      if (close(pfd1[0]) == -1) 
      { 
       printf("Error closing reading end of pipe 1.\n"); 
       _exit(1); 
      } 
      /* close writing end of second pipe */ 
      if (close(pfd2[1]) == -1) 
      { 
       printf("Error closing writing end of pipe 2.\n"); 
       _exit(1); 
      } 

      /* write to pipe 1 */ 
      if (write(pfd1[1], messageOne, commLen) != commLen) 
      { 
       printf("Error writing to pipe 1.\n"); 
       _exit(1); 
      } 

      if (close(pfd1[1]) == -1) 
      { 
       printf("Error closing writing end of pipe 1.\n"); 
       _exit(1); 
      } 

      /* reding from pipe 2 */ 
      numRead = read(pfd2[0], buf, commLen); 
      if (numRead == -1) 
      { 
       printf("Error reading from pipe 2.\n"); 
       _exit(1); 
      } 

      if (close(pfd2[0]) == -1) 
      { 
       printf("Error closing reding end of pipe 2.\n"); 
       _exit(1); 
      } 

      printf("Message received child ONE: %s", buf); 
      printf("Exiting child 1...\n"); 
      _exit(0); 

     default: 
      break; 
    } 

    // child 2 
    switch (fork()) 
    { 
     case -1: 
      printf("Error forking child 2!\n"); 
      exit(1); 
     case 0: 
      printf("\nChild 2 executing...\n"); 
      /* close reading end of second pipe */ 
      if (close(pfd2[0]) == -1) 
      { 
       printf("Error closing reading end of pipe 2.\n"); 
       _exit(1); 
      } 
      /* close writing end of first pipe */ 
      if (close(pfd1[1]) == -1) 
      { 
       printf("Error closing writing end of pipe 1.\n"); 
       _exit(1); 
      } 

      /* read from the first pipe */ 
      if (read(pfd1[0], buf, commLen) == -1) 
      { 
       printf("Error reading from pipe 1.\n"); 
       _exit(EXIT_FAILURE); 
      } 

      if (close(pfd1[0]) == -1) 
      { 
       printf("Error closing reading end of pipe 1.\n"); 
       _exit(EXIT_FAILURE); 
      } 

      /* write to the second pipe */ 
      if (write(pfd2[1], messageTwo, commLen) != commLen) 
      { 
       printf("Error writing to the pipe."); 
       _exit(EXIT_FAILURE); 
      } 

      if (close(pfd2[1]) == -1) 
      { 
       printf("Error closing writing end of pipe 2."); 
       _exit(EXIT_FAILURE); 
      } 

      printf("Message received child TWO: %s", buf); 
      printf("Exiting child 2...\n"); 
      _exit(EXIT_SUCCESS); 

     default: 
      break; 
    } 

    printf("Parent closing pipes.\n"); 

    if (close(pfd1[0]) == -1) 
    { 
     printf("Error closing reading end of the pipe.\n"); 
     exit(EXIT_FAILURE); 
    } 

    if (close(pfd2[1]) == -1) 
    { 
     printf("Error closing writing end of the pipe.\n"); 
     exit(EXIT_FAILURE); 
    } 

    if (close(pfd2[0]) == -1) 
    { 
     printf("Error closing reading end of the pipe.\n"); 
     exit(EXIT_FAILURE); 
    } 

    if (close(pfd1[1]) == -1) 
    { 
     printf("Error closing writing end of the pipe.\n"); 
     exit(EXIT_FAILURE); 
    } 

    printf("Parent waiting for children completion...\n"); 
    if (wait(NULL) == -1) 
    { 
     printf("Error waiting.\n"); 
     exit(EXIT_FAILURE); 
    } 

    if (wait(NULL) == -1) 
    { 
     printf("Error waiting.\n"); 
     exit(EXIT_FAILURE); 
    } 

    printf("Parent finishing.\n"); 
    exit(EXIT_SUCCESS); 
} 
+0

第二個fork命令將由child1和parent執行。會不會造成問題? – Mani

0

你的邏輯是倒退用於確定給定進程是否是父母或子女。孩子從fork得到0,父母得到孩子的pid。據推測,希望兩個孩子能有相同的父,在這種情況下,第一if應該是:

if(chld_1 != 0) 

而且,家長應該在其中既chld_1chld_2是非零的過程:

if(chld_1 != 0 && chld_2 != 0) 

此外,您應該錯誤檢查兩個fork s(返回-1表示錯誤)。

相關問題