使用管道连接子进程

时间:2014-05-06 14:28:15

标签: c process pipe child-process

我想创造一些中国私语(或电话)游戏。

我创建了一定数量的子进程,每个子进程都必须从字符串中更改1个字母。父进程更改一个字母,然后第一个子进程更改父进程修改的字符串并再更改一个字母。第二个孩子接受第一个孩子修改的字符串(2个字母已经更改)并再更改一个,依此类推。

因此,我想将父母和第一个孩子以及每两个连续的孩子用管道连接起来。 问题是这对3个以上的孩子不起作用。第三个孩子不从第二个孩子读取,它从父母那里读取。你能告诉我我做错了吗?

    int nrch;
    nrch=(int) strtol(argv[2], (char **)NULL, 10);
    msg=argv[3];
    printf("Parent: erhalten: %s\n", msg);
    int i=0;
    msg=modify(argv[3],nrch);
    printf("Parent: weiter: %s\n", msg);
    pid_t pids[10];
    int fd[2];
    int fdold[2];

    if (pipe(fdold) == -1) {
        error("Can't create the pipe");
    }

    /* Start children. */
    for (i = 0; i < nrch; ++i) {
        if (pipe(fd) == -1) {
            error("Can't create the pipe");
        }
        if ((pids[i] = fork()) < 0) {
                error("Can't fork process");
        } 
        else if (pids[i] == 0) {

            //dup2(fd[0], 0);
            if(i==0){
                close(fdold[1]);
                close(fd[0]);
                read(fdold[0],msg,sizeof(msg));
                printf("child%d: erhalten: %s\n", (i+1), msg);
                    msg=modify(msg,i);
                printf("child%d: weiter: %s\n", (i+1), msg);
                write(fd[1],msg,sizeof(msg));   
                exit(0);
            }
            else if(i==(nrch-1)){
                close(fdold[1]);
                read(fdold[0],msg,sizeof(msg));
                printf("child%d: erhalten: %s\n", (i+1), msg);
                    msg=modify(msg,i);
                printf("child%d: weiter: %s\n", (i+1), msg);
                printf("child%d: Ende: %s\n", (i+1), msg);

                    exit(0);
            }
            else{
                close(fdold[1]);
                close(fd[0]);
                read(fdold[0],msg,sizeof(msg));

                printf("child%d: erhalten: %s\n", (i+1), msg);
                    msg=modify(msg,i);
                printf("child%d: weiter: %s\n", (i+1), msg);

                write(fd[1],msg,sizeof(msg));   
                exit(0);
            }
        }
        else{
            if(i!=0){
                close(fd[1]);
            }
            else{
                write(fdold[1], msg,sizeof(msg));

            }
            if(i>1){
                close(fdold[0]);
            }
        }
        pid_t wpid;
        int status;
        wpid = wait(&status);
        memcpy(fdold,fd,(sizeof(int)*2));
    }   
    close(fd[0]);

1 个答案:

答案 0 :(得分:1)

我认为你孩子的代码过于复杂。在循环的每次迭代中,您似乎也都是从父级写入的。

您为每个子进程正确创建了一个管道,但是我没有看到将管道的一侧从一个兄弟传递到另一个兄弟的机制,这是父进程需要管理的内容。

在下面的代码中,我使用父节点中的prev_in将管道的读取端最初从父节点传递给第一个子节点,然后从兄弟节点传递给兄弟节点,最后父节点将其用作其管道的读取端。

我没有检查此代码是否存在可能存在的任何缓冲区溢出问题,我只查看了文件描述符管理问题,您应该注意检查其他错误。

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

char *modify (char *word, int num)
{
  printf ("Modify `%s', (%d)\n", word, num);
  word [num] = 'x';
  return word;
}

void
whisper (int id, int in, int out)
{
  char msg [100];

  read(in, msg, sizeof(msg));
  printf("child%d: heard: %s\n", id, msg);
  modify (msg, id);
  printf("child%d: says: %s\n", id, msg);
  write(out, msg, sizeof(msg));
}

void
start_whisper (int in, int out, char *msg)
{
  char buf [100];

  printf ("Parent, starting a whisper with `%s'\n", msg);
  write(out, msg, strlen (msg) + 1); /* Also send the NUL.  */

  read(in, buf, sizeof(buf));
  printf("Parent, heard back: %s\n", buf);
}

int
main (int argc, char *argv [])
{
  int nrch, i;
  char *msg;
  pid_t pids[10];

  nrch=(int) strtol(argv[2], (char **)NULL, 10);
  printf ("Number of children = %d\n", nrch);

  msg = argv[3];
  printf("Parent: original message: %s\n", msg);

  if (nrch == 0 || nrch > strlen (msg))
    error ("Invalid number of children");

  msg = modify (msg, nrch);
  printf("Parent: will start by saying: %s\n", msg);

  int fdold[2];
  int prev_in, parent_in, parent_out;

  if (pipe(fdold) == -1) {
    error("Can't create the pipe");
  }
  printf ("Parent Read: %d, Write: %d\n", fdold [0], fdold [1]);

  parent_in = fdold [0];
  parent_out = fdold [1];

  /* Start children. */
  prev_in = parent_in;
  for (i = 0; i < nrch; ++i)
    {
      int fd[2];
      if (pipe (fd) == -1) {
        error ("Can't create the pipe");
      }
      if ((pids[i] = fork()) < 0) {
        error("Can't fork process");
      }
      else if (pids[i] == 0)
        {
          /* Child.  */
          int my_in, my_out;

          close (fd [0]); /* The sibling read handle, this becomes prev_in
                             and is passed to the next sibling.  */
          close (parent_out); /* The parent write handle, only the parent
                                 wants to hold this, every child will
                                 close it.  */

          my_in = prev_in;
          my_out = fd [1];

          whisper (i, my_in, my_out);
          exit (0);
        }
      else
        {
          /* Parent.  */
          close (prev_in); /* The PREV_IN was passed the child we just
                              created, we no longer need this.  */
          prev_in = fd [0]; /* The read handle from the pipe we just made
                               will be passed to the next sibling.  */
          close (fd [1]); /* The write handle from the pipe we just made
                             was grabbed by the child we just made, we no
                             longer need this.  */
        }
    }

  start_whisper (prev_in, fdold [1], msg);

  pid_t wpid;
  int status;
  wpid = wait(&status);

  return 0;
}