0

我正在實驗室工作。 父進程將創建兩個子進程A和B. 子A將通過pipe向子B發送一些字符串.son B將從子A獲得的字符串的字符串大小寫反轉,並將反向字符串發回給子A 。收到倒子串A後,將其打印到屏幕上。在IPC中通過管道需要幫助

這裏是代碼。

#include <stdio.h> 
#include <unistd.h> 
#include <stdlib.h> 
#include <ctype.h> 

void process_A(int input_pipe[], int output_pipe[]) 
{ 
    int c;  
    char ch; 
    int rc; 


    close(input_pipe[1]); 
    close(output_pipe[0]); 

    while ((c = getchar()) > 0) { 
     ch = (char)c; 
     rc = write(output_pipe[1], &ch, 1); 
    if (rc == -1) { 
     perror("A_TO_B: write"); 
     close(input_pipe[0]); 
     close(output_pipe[1]); 
     exit(1); 
     } 

    rc = read(input_pipe[0], &ch, 1); 
    c = (int)ch; 
    if (rc <= 0) { 
     perror("A_TO_B: read"); 
     close(input_pipe[0]); 
     close(output_pipe[1]); 
     exit(1); 
     } 
    putchar(c); 
    } 
    close(input_pipe[0]); 
    close(output_pipe[1]); 
    exit(0); 
} 

void process_B(int input_pipe[], int output_pipe[]) 
{ 
    int c; 
    char ch; 
    int rc; 
    close(input_pipe[1]); 
    close(output_pipe[0]); 
    while (read(input_pipe[0], &ch, 1) > 0) { 
     c = (int)ch; 
     if (isascii(c) && isupper(c)) 
      c = tolower(c); 
      else if (isascii(c) && islower(c)) 
      c = toupper(c); 
     ch = (char)c; 
     rc = write(output_pipe[1], &ch, 1); 
     if (rc == -1) { 
      perror("B_TO_A: write"); 
      close(input_pipe[0]); 
      close(output_pipe[1]); 
      exit(1); 
     } 
    } 

    close(input_pipe[0]); 
    close(output_pipe[1]); 
    exit(0); 
} 


int main(int argc, char* argv[]) 
{ 
    /* 2 arrays to contain file descriptors, for two pipes. */ 
    int A_TO_B[2]; 
    int B_TO_A[2]; 
    int pid;  
    int rc,i,State;  

    /* first, create one pipe. */ 
    rc = pipe(A_TO_B); 
    if (rc == -1) { 
    perror("main: pipe A_TO_B"); 
    exit(1); 
    } 
    /* create another pipe. */ 
    rc = pipe(B_TO_A); 
    if (rc == -1) { 
    perror("main: pipe B_TO_A"); 
    exit(1); 
    } 

    for(i=0;i<2;i++) 
    { 
     if((pid=fork()) <0){perror("fork failed\n");}; 
     if((i==0) && (pid ==0)) 
     { 
      process_A(A_TO_B, B_TO_A); 
     } 
     else if((i==1)&&(pid==0)) 
     { 
      process_B(B_TO_A, A_TO_B); 
     } 
     else if(pid>0) 
     { 
      wait(&State);   
     } 
    } 

    return 0; 
} 

問題是當我運行程序的兒子B獲取塊。 我需要你們的幫助。 在此先感謝。

回答

2

OK,圖表:

initially: parent process: has 
    B_TO_A[0] and [1] open, 
    has A_TO_B[0] and [1] open 
fork (makes copy) 
parent:        child (pid==0): 
B_TO_A both open, A_TO_B both open  call process_A: close unwanted pipe ends, loop 

call wait(), wait for one child  loop reads stdin, writes one pipe, reads other pipe 

if we ever get here: 

fork (makes copy) 
parent:        child (pid==0): 
B_TO_A both open, A_TO_B both open  call process_B: close unwanted pipe ends, loop 

parent: both ends of both pipes open 
call wait(), wait for one child  loop reads one pipe, writes other pipe 

首先,你通常不會得到「如果我們到這裏來」,因爲孩子在stdin運行process_A()循環運行,直到EOF(如果是第一次出現)或其中一個管道讀取/寫入調用失敗(例如,由於input_pipe[0]上的EOF)。由於父節點仍在wait()調用中等待,並且兩個管道的兩端都打開,所以管道上沒有EOF(讀取所有寫入者寫入的所有數據後,管道上出現EOF,並且所有的數據都是dup s寫入結束已關閉)。所以唯一的方法就是在stdin上打EOF,這樣while循環就不會運行。第二,如果你真的想再次分手並做process_B(),那個孩子也會永遠等下去,因爲它讀取的管道的一個寫入端仍然是打開的......在父項中!父母不會關閉它,因爲父母將永遠等待wait

在一般情況下,你需要做的是:

  • 創建兩個管道(像現在一樣)
  • 叉一次,並在孩子再次
  • 叉運行process_A()(在父母),並在(新的)孩子
  • 接近後兩個管道的兩端(父)
  • 等待兩個孩子現在,運行process_B()因爲你必須做一些事情(如kill()的第一個孩子),如果您不能啓動第二個孩子0雙方都開始變得

錯誤處理變得有點凌亂。所以你需要知道你有多遠。您仍然可以循環兩次,但在循環內不能循環wait,並且只需循環兩次,每次循環都執行相當不同的步驟,那麼不妨將它全寫出來,不要循環。

+0

它幫助我100%。 謝謝torek。 – devoidfeast 2012-03-20 23:20:56