Académique Documents
Professionnel Documents
Culture Documents
Agora, vamos fazer algo um pouco mais complexo e interessante: não vamos somente
enviar a informação em um sentido (escrevendo de um lado, e lendo de outro), vamos fazer
com que um processos escreva e leia, e o outro também.
Depois ocorre o contrário, o processo que esperava é que vai escrever, e o outro é que tem
que esperar. Isso é o sincronismo entre pipes, saber quando cada processo deve agir.
Uma solução para este tipo de situação, bem corriqueira em sistemas operacionais, é através
do uso de dois pipes. Veja a imagem que ilustra essa solução:
O grande 'segredo' da coisa é a variável 'turn', existente em cada processo, que começa com
valor 0.
Turn em inglês quer dizer turno, vez, rodada...ou seja, essa variável vai ditar as regras sobre
o que cada processo deve fazer em cada momento.
Depois da criação dos pipes e do uso da chamada de sistema fork(), entramos no processo
pai.
Aqui, declaramos o vetor de inteiros num que vai armazenar os dois inteiros do usuário, e o
inteiro soma que vai receber o valor da soma dos filhos.
Em seguida devemos fechar os 'lados' do pipe que não vamos usar no processo pai, pela
figura acima vemos que é o fd1[0] e o fd2[1], através da função close.
Agora o processo pai e o filho entram em looping infinito, definido por while(1).
Vamos definir dois estados, que ditarão as regras do sincronismo.
O primeiro estado é quando turn=0, aqui vai acontecer duas coisas: o pai vai pedir os
números ao usuário e o filho vai esperar por esses dados.
Os números enviados pelo pai estão em um vetor, então basta passarmos o nome desse
vetor e o número de bytes que queremos passar pela função write(), este número é o
tamanho da variável num (que é calculado por sizeof(num) ).
Quando o pai termina essa tarefa, ele passa o estado para turn=1
Ainda no filho, em turn=0, ele vai receber um vetor e vai fazer a sua variável numeros,
que é um ponteiro, apontar para esse vetor que recebeu pela função read, e vai ler
sizeof(numeros) bytes.
Em suma: ele vai receber o vetor de inteiros com duas posições, pois foi isso que o pai
passou.
Agora que recebeu, também muda seu estado para turn=1
Ok, o pai enviou e o filho recebeu, essa primeira parte já foi. Agora é turn=1
Neste passo, o filho calcula a soma dos dois números (na qual o vetor numeros aponta) e
manda esses eles via função write para o pipe. No fim do processo filho, ele volta para
turn=0, para que tudo posso ocorrer de novo.
Do outro lado do pipe, ainda no estágio turn=1, o processo pai fica esperando um inteiro
através do pipe, usando a read.
Assim que recebe, armazena esse inteiro em sua variável soma, que é um inteiro.
Por fim, o pai exibe a soma e retorna para o valor turn=0, para que o processo volte do
começo.
int main(void) {
int fd1[2], /* Pai vai escrever e Filho ler por esse file
descriptor */
fd2[2], /* Pai vai ler e o Filho escrever por esse file
descriptor */
turn=0; /* Vai definir o que cada um vai fazer (ler,
escrever, aguardar...) */
pid_t pid; /* Armazena o pid, para o tratamento de pai e filho
*/
/* Cria o pipe 1 */
if(pipe(fd1)<0) {
perror("pipe") ;
return -1 ;
}
/* Cria o pipe 2 */
if(pipe(fd2)<0) {
perror("pipe") ;
return -1 ;
}
if(pid == -1) {
perror("fork") ;
return -1 ;
}
close(fd2[0]);
close(fd1[1]);
} else {
int numeros[2],
soma;
while(1){
if(turn==0){ /* Filho vai ler o vetor de numeros do pai */
read(fd1[0], numeros, sizeof(numeros) ); /* Recebeu o
vetor de inteiros do pai e colocou no vetor 'numeros' */
turn=1; /* Passa para o próximo passo, que é o filho
somar e escrever o resultado da soma */
}else
close(fd2[1]);
close(fd1[0]);
}
return 0 ;
}