C 使用管道连接子进程

C 使用管道连接子进程,c,process,pipe,child-process,C,Process,Pipe,Child Process,我想创造一些中国的耳语(或电话)游戏 我创建了一定数量的子进程,每个子进程必须更改字符串中的一个字母。父进程更改一个字母,然后第一个子进程接受父进程修改的字符串并再更改一个字母。第二个子项接受由第一个子项修改的字符串(已经更改了两个字母),然后再更改一个,以此类推 因此,我想用管道将父对象和第一个子对象以及每个连续的两个子对象链接起来。 问题是,这对3个以上的孩子不起作用。第三个子对象不从第二个子对象读取数据,而是从父对象读取数据。你能告诉我我做错了什么吗 int nrch; n

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

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

因此,我想用管道将父对象和第一个子对象以及每个连续的两个子对象链接起来。 问题是,这对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]);
int-nrch;
nrch=(int)strtol(argv[2],(char**)NULL,10);
msg=argv[3];
printf(“父项:erhalten:%s\n”,msg);
int i=0;
msg=修改(argv[3],nrch);
printf(“父项:weiter:%s\n”,msg);
pid_t pid[10];
int-fd[2];
int-fdold[2];
if(管道(fdold)=-1){
错误(“无法创建管道”);
}
/*生孩子*/
对于(i=0;i1){
关闭(fdold[0]);
}
}
pid_t wpid;
智力状态;
wpid=等待(&status);
memcpy(fdold,fd,(sizeof(int)*2));
}   
关闭(fd[0]);

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

您正确地为每个子进程创建了一个管道,但我没有看到将管道的一侧从一个同级传递到下一个同级的机制,这是父进程需要管理的

在下面的代码中,我在父级中使用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;
}
#包括
#包括
#包括
字符*修改(字符*字,整数)
{
printf(“修改“%s”,(%d)\n),单词,数字);
字[num]=“x”;
返回词;
}
无效的
耳语(int-id,int-in,int-out)
{
char-msg[100];
读取(in、msg、sizeof(msg));
printf(“子%d:heard:%s\n”,id,msg);
修改(msg,id);
printf(“子%d:表示:%s\n”,id,msg);
写出(信息、消息、消息大小);
}
无效的
开始耳语(输入、输出、字符*msg)
{
char-buf[100];
printf(“家长,用“%s”\n开始耳语”,msg);
写下(out,msg,strlen(msg)+1);/*同时发送NUL*/
读(in,buf,sizeof(buf));
printf(“父项,回音:%s\n”,buf);
}
int
main(int argc,char*argv[])
{
int nrch,i;
char*msg;
pid_t pid[10];
nrch=(int)strtol(argv[2],(char**)NULL,10);
printf(“子项数量=%d\n”,nrch);
msg=argv[3];
printf(“父:原始消息:%s\n”,msg);
如果(nrch==0 | | nrch>strlen(msg))
错误(“无效的子项数”);
msg=修改(msg,nrch);
printf(“父项:将以说:%s\n”开始,msg);
int-fdold[2];
int prev\u in、parent\u in、parent\u out;
if(管道(fdold)=-1){
错误(“无法创建管道”);
}
printf(“父读取:%d,写入:%d\n”,fdold[0],fdold[1]);
父项_in=fdold[0];
parent_out=fdold[1];
/*生孩子*/
prev_in=父项_in;
对于(i=0;i