0

我想要一个父母和两个孩子。

父母从文件“a.txt”中读取并将槽管道发送给第一个孩子;第一个孩子读取字符并将小写字母字符发送给第二个孩子。

第二个孩子在“b.txt”中打印每个不同的字符和出现次数(每行),然后通过管道向父级发送不同字符的数量。父母打印第二个孩子的结果。

我已经完成了从父母到 1 个孩子的管道,为了测试我已经把管道放回了父母。我想不通的是如何让管道进入第二个孩子。我一直在寻找有关信息,dup2但我不知道如何使它工作。

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
#include <ctype.h>
#include <fcntl.h>

void main()
{

    int pfd1[2], pfd2[2], pid1, pid2, pfin, status, fd;
    char *c = (char *)malloc(sizeof(char));

    if (pipe(pfd1) < 0) {
        printf("Eroare la crearea pipe-ului\n");
        exit(1);
    }
    if (pipe(pfd2) < 0) {
        printf("Eroare la crearea pipe-ului\n");
        exit(1);
    }
    if ((pid1 = fork()) < 0) {
        printf("Eroare la fork\n");
        exit(1);
    }

    if (pid1 == 0) {    /*child */
        close(pfd1[1]);
        while (read(pfd1[0], c, 1) > 0) {
            //printf("%s",c);
            if (islower(*c)) {
                close(pfd2[0]);
                //inchid capul de citire; scriu in pipe
                write(pfd2[1], c, 1);
                ////dup??????
            }
        }
        printf("\n");
        write(pfd[1], buff, len);

        close(pfd1[0]);
        close(pfd2[1]);
        exit(0);
    }

    if ((pid2 = fork()) < 0) {
        printf("Eroare la fork\n");
        exit(1);
    }

    if (pid2 == 0) {
        printf("second child");
        exit(0);
    }

    /* parent */
    close(pfd1[0]);
    close(pfd2[1]);
    fd = open("date.txt", O_RDONLY);
    while (read(fd, c, 1) > 0) {
        write(pfd1[1], c, 1);
    }
    close(pfd1[1]);     /* la sfarsit inchide si capatul utilizat */
    close(pfin);

    while (read(pfd2[0], c, 1) > 0)
        printf("%s", c);
    close(pfd2[0]);
    printf("%d", wait(&status));
    printf("%d", wait(&status));

}
4

3 回答 3

2

我对您的代码有一些具体的评论:

char *c = (char *)malloc(sizeof(char));

虽然这没有什么问题,但也没有必要char从堆中分配它。更惯用的方法将char c;在这里使用,然后传递&cread(2)write(2)系统调用。(更惯用的方法是使用 C 标准 IO 工具;freopen(3)、、getchar(3)putchar(3)-- 但在您让此代码完全按照您希望的方式工作之前不要进行这种转换,因为它是您遇到的问题的额外复杂性试图解决。)

if ((pid1 = fork()) < 0) {
    printf("Eroare la fork\n");
    exit(1);
}

通过使用您自己的错误消息,您会错过重要的错误信息。您应该使用perror(3)来打印错误消息。这将为您和您的用户提供他们可以搜索的错误的实际原因。fork(2)如果您的用户运行到setrlimit(2) NPROC最大进程限制,系统范围的进程限制,内核内存不足,则可能会失败。

if ((pid1 = fork()) < 0) {
   perror("Eroare la fork");
   exit(1);
}

您还应该检查open(2)调用的返回值。(您还应该检查错误的返回值write(2)close(2)但处理这些错误更难。简单地打印错误并退出对于大多数程序来说是一个好的开始。)

    while (read(pfd1[0], c, 1) > 0) {
        //printf("%s",c);
        if (islower(*c)) {
            close(pfd2[0]);

这是close(2)调用的错误位置——您不应该为每个输入字符一遍又一遍地关闭此文件描述符。如果您正在检查close(2)返回值,您会注意到errno设置为,EBADF因为文件描述符在第二次和后续调用中不再有效。

现在,您来这里解决的问题是: 、 和 调用的顺序fork()pipe()连接dup2()管道中的所有进程并将数据发送回父进程。由于pipe(2)创建单向pipe(7)s,您需要调用pipe(2) 四次- 用于父子之间的两个方向。如果您将管道端点存储在具有对您有意义的名称的数组中,那么它们将更容易跟踪。也许创建命名to_为写入和from_读取的数组:

int to_child[2];
int from_parent[2];
int to_parent[2];
int from_child[2];

for (int i=0; i<2; i++) {
    int p[2];

    if (pipe(p) == -1) {
    perror("pipe");
    exit(1);
    }

    /* from parent to child */

    to_child[i] = p[1];
    from_parent[i] = p[0];

    if (pipe(p) == -1) {
    perror("pipe");
    exit(1);
    }

    /* from child to parent */

    to_parent[i] = p[1];
    from_child[i] = p[0];
}

请注意,您实际上不需要重新dup2(2)排列文件描述符,除非您想执行其他程序来处理“过滤”任务。只需read(2)使用from_parent[...]orfrom_child[...]描述符和write(2)andto_child[...]描述to_parent[...]符。

也许socketpair(2)使用AF_UNIX创建双向套接字会更容易,然后可以以与任何其他 BSD 样式套接字相同的方式读取和写入。请参阅socket(7)unix(7)了解概述。

于 2012-01-11T00:24:39.673 回答
0

你不需要dup()。只需在父级中打开管道,然后在每个进程中close()打开您不需要的端点,然后使用您确实需要的端点。

请注意,这意味着父级将关闭管道的两个端点以进行子-子通信。该管道的每个端点都将由其中一个孩子使用。每个孩子还应该关闭它不使用的端点。

于 2012-01-11T21:06:45.737 回答
0

谢谢您的回答。这是整个问题的代码。

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
#include <ctype.h>
#include <fcntl.h>

void main()
{

 int pfd1[2],pfd2[2],pfd3[2],pid1,pid2,status,fd,fo;
 char letter[32][2];
 int letternumber=0,i,sw=0;
 char* c = (char*)malloc(sizeof(char));
 //pipe creation
 if(pipe(pfd1)<0){ 
    perror("Eroare la crearea pipe-ului"); 
    exit(1); 
 } 

 if(pipe(pfd2)<0){ 
    perror("Eroare la crearea pipe-ului\n"); 
    exit(1); 
 }

 if(pipe(pfd3)<0){ 
    perror("Eroare la crearea pipe-ului\n"); 
    exit(1); 
 }  
 //make first child
 if((pid1=fork())<0){ 
    perror("Eroare la fork\n"); 
    exit(1); 
 } 
 if(pid1==0) //child process
 { 
 if(close(pfd1[1])<0) {perror("Eroare close");exit(1);} // close write end; process will read from pipe
 if(close(pfd2[0])<0) {perror("Eroare close");exit(1);} //close read end; write in pipe
 while (read(pfd1[0], c, 1) > 0){
    if(islower(*c))  write(pfd2[1],c,1);//writing in pipe

 }
 if(close(pfd1[0])<0) {perror("Eroare close");exit(1);} /* close other ends */ 
 if(close(pfd2[1])<0) {perror("Eroare close");exit(1);}
 if(close(pfd3[0])<0) {perror("Eroare close");exit(1);}
 if(close(pfd3[1])<0) {perror("Eroare close");exit(1);}
 exit(0); 
 } 


 //make second child
 if((pid2=fork())<0){ 
  perror("Eroare la fork"); 
  exit(1); 
 } 

 if(pid2==0){ /* second child*/ 
      if(close(pfd1[0])<0) {perror("Eroare close");exit(1);}
  if(close(pfd1[1])<0) {perror("Eroare close");exit(1);}
  if((fo=open("statistica.txt", O_CREAT | O_TRUNC | O_RDWR, 
                S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | 
                S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IROTH))==-1)
    {perror("Eroare open");exit(1);}
  if(close(pfd2[1])<0) {perror("Eroare close");exit(1);}
  letter[0][0]='A';
  letter[0][1]=0;
  while(read(pfd2[0],c,1)>0) {          
    for(i=0;i<=letternumber;i++) 
          if(letter[i][0]==*c) {letter[i][1]++;sw=1;}
    if (sw==0){
          letter[letternumber][0]=*c;
          letter[letternumber++][1]=1;
    }     
    sw=0;    
  }
  printf("\n");//why won't it write to file without it; 
                   //wihtout it, it writes to screen?
  if(close(pfd2[0])<0) {perror("Eroare close");exit(1);}
  dup2(fo,1);
  for(i=0;i<letternumber;i++) 
      printf("%c %d\n",letter[i][0],letter[i][1]);
  if(close(fo)<0) {perror("Eroare close");exit(1);}
  if(close(pfd3[0])<0) {perror("Eroare close");exit(1);} //close read end; going to write in pipe
  dup2(pfd3[1],1);
  printf("%d",letternumber);
  if(close(pfd3[1])<0) {perror("Eroare close");exit(1);}
  exit(0);
 }  

 /* parent process */ 
 if(close(pfd1[0])<0) {perror("Eroare close");exit(1);} // close read end; write in pipe
 if(close(pfd2[0])<0) {perror("Eroare close");exit(1);}
 if(close(pfd2[1])<0) {perror("Eroare close");exit(1);}
 if(close(pfd3[1])<0) {perror("Eroare close");exit(1);}

 if((fd=open("date.txt",O_RDONLY))==-1)
  {perror("Eroare open");exit(1);}

 while(read(fd,c,1)>0)
      write(pfd1[1],c,1); //write in pipe

 if(close(pfd1[1])<0) {perror("Eroare close");exit(1);}
 //dup2(pfd3[0],0);
 while(read(pfd3[0],c,1)>0) printf("%c",*c);
 printf("\n");
 if(close(pfd3[0])<0) {perror("Eroare close");exit(1);}
 wait(&status);
 wait(&status);
}
于 2012-01-12T12:09:12.630 回答