2012-01-10 53 views
0

我想有一個家長和2個孩子。進程間的管道鏈接

父文件從文件「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)); 

} 

回答

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)可能會失敗,如果您的用戶正在運行到最大進程限制,即系統範圍進程限制,超出內核內存。

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)四次 - 適用於父母與子女之間的兩個方向。如果您將管道端點存儲在名稱對您而言意義重大的數組中,則它們將更易於跟蹤。

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)重新安排filedescriptors除非你想執行其他方案爲:對於寫入用於讀取也許創建一個名爲to_陣列和from_處理「過濾器」任務。只需read(2)使用from_parent[...]from_child[...]描述符和write(2)使用to_child[...]to_parent[...]描述符。

也許整個事情會使用AF_UNIX創建雙向插座,然後可以讀取並以相同的方式寫入到任何其他BSD風格的插座socketpair(2)容易。有關概述,請參見socket(7)unix(7)

0

您不需要dup()。只需在父級中打開管道,然後在每個進程中您不需要的端點,只需使用您需要的端點即可。

請注意,這意味着父級將關閉子級和子級通信的管道的兩個端點。該管道的每個端點都將由其中一個孩子使用。每個孩子還應該關閉它不使用的端點。

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