简体   繁体   English

使用管道连接子进程

[英]Using pipes to connect child processes

I would like to create some kind of Chinese whispers (or telephone) game. 我想创建某种中国的耳语(或电话)游戏。

I create a certain number of child processes, each child process having to change 1 letter from a string.The parent changes one letter, then the first child takes the string modified by the parent and changes one more letter. 我创建了一定数量的子进程,每个子进程必须从字符串中更改一个字母。父级更改一个字母,然后第一个子级采用父级修改的字符串并再更改一个字母。 The second child takes the string modified by the first one (2 letters are already changed) and changes one more and so on. 第二个孩子采用第一个孩子修改过的字符串(已经更改了2个字母),然后再更改一个,依此类推。

Therefore I would like to link the parent and the first child and each two consecutive children with a pipe. 因此,我想用管道将父母和第一个孩子以及每个连续的两个孩子联系起来。 The problem is that this does not work for more than 3 children. 问题是这不适用于3个以上的孩子。 The third child does not read from the second one, it reads from the parent. 第三个孩子不读第二个孩子,而是从父母那里读。 Could you please tell me what I am doing wrong? 你能告诉我我在做什么错吗?

    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]);

I think your code for the child is overly complex. 我认为您为孩子编写的代码过于复杂。 You also appear to be writing from the parent in every iteration of the loop. 在循环的每次迭代中,您似乎也都在从父级进行书写。

You correctly create a pipe for each child process, but I don't see a mechanism for passing one side of the pipe from one sibling to the next, this is something that the parent will need to manage. 您为每个子进程正确创建了一个管道,但是我看不到一种将管道的一侧从同级传递到另一侧的机制,这是父级需要管理的机制。

In the code below I use prev_in within the parent to pass the read side of a pipe initially from the parent to the first child, and then from sibling to sibling, finally the parent uses this as the read side of its pipe. 在下面的代码中,我在父级中使用prev_in将管道的读取端最初从父级传递到第一个孩子,然后从同级传递到同级,最后父级将其用作管道的读取端。

I've not checked this code for any buffer overrun problems that might exist, I've only looked at the file descriptor management issues, you should probably take care to check for other errors. 我没有检查此代码中是否存在任何可能存在的缓冲区溢出问题,我仅查看了文件描述符管理问题,您可能应该注意检查其他错误。

#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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM