2011-07-29 276 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表示错误)。

相关问题