0

Я работаю над лабораторией. Отцовский процесс создаст процессы с двумя сыновьями A и B. Сын А пошлет некоторую строку сыну B через pipe.son B будет инвертировать случай строки String Got from Son 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; 
} 

Проблема заключается в том, что при запуске программы Son B получает Block. Мне нужно, чтобы ребята помогли. Спасибо заранее.

ответ

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 

Во-первых, вы, как правило, не получается «если мы когда-нибудь здесь», потому что ребенок не работает process_A() прогонов в цикле, пока либо EOF на стандартный ввод (если это происходит первая) или один из вызовов чтения/записи канала не работает (например, из-за EOF на input_pipe[0]). Поскольку родитель все еще ждет вызова wait() и открывается оба конца обоих труб, на трубе нет EOF (EOF на трубе происходит после того, как вы прочитали все данные, написанные всеми авторами, и все dup с конец записи закрыт). Таким образом, единственный способ попасть туда - нажать EOF на stdin, так что цикл while не запускается.

Во-вторых, если вы снова обходите форкировку и делаете process_B(), этот ребенок также будет ждать всегда, потому что один конец записи трубы, которую он читает, по-прежнему открыт ... в родительском! Родитель не будет закрывать его, потому что родитель будет ждать навсегда в wait.

В общем, что вам нужно сделать здесь:

  • создать две трубы (как вы делаете сейчас)
  • вилкой один раз, и запустить process_A() у ребенка
  • вилка снова (в родитель), и запустить process_B() в (новое) ребенок
  • близко оба конца обоего труб (в родителю)
  • ожидания для детей в настоящее время, после того, как оба получиут начали

Обработка ошибок становится немного грязной, так как вы должны сделать что-то (например, kill() первым ребенком), если вы не можете запустить второй ребенок. Поэтому вам нужно знать, как далеко вы достигли. Вы все еще можете зацикливаться на fork два раза, но вы не можете wait внутри цикла, и всего две поездки вокруг цикла, каждая из которых выполняет несколько разных шагов, вы можете просто написать все это без цикла.

+0

Это помогло мне на 100%. спасибо torek. – devoidfeast

 Смежные вопросы

  • Нет связанных вопросов^_^