05 01 comunicacao inter processo
TRANSCRIPT
Sistemas Operacionais
Comunicação Inter-processos
id4305299 pdfMachine by Broadgun Software - a great PDF writer! - a great PDF creator! - http://www.pdfmachine.com http://www.broadgun.com
Comunicação Inter Processos
1) Como um processo passa informações para outro processo;
2) Como garantir que dois ou mais processos não invadam unsaos outros, quando envolvidos em regiões críticas. Por exemplo,suponha que dois processos tentem, cada um, acessar umadeterminada região de memória.
3) O relacionamento, ou sequência adequada, quando existirdependência entre processos. Se o processo A produz dados e oprocesso B os imprime, B deve esperara até que A produzaalguns dados para serem impressos.
Comunicação Inter-Processos
� Os processos frequentemente precisam se comunicar com outros processos
� O modelo de comunicação adotado precisa resolver 3 questões:� Como passar informações de um processo para o outro
sem envolver interrupções
� Garantir que dois ou mais processos não interfiram um com o outro quando envolvidos em atividades críticas
� Respeitar a dependência existente entre os processos
Comunicação Inter-Processos
� Motivos para prover um ambiente quepermita a cooperação entre processos.� Compartilhamento de informações. Como diversos usuários podem
estar interessados na mesma informação, temos que prover umambiente para permitir acesso concorrente a tais informações.
� Agilidade na computação. Se queremos que determinada tarefa sejaexecutada mais rapidamente, temos que dividi-las em sub tarefas,cada uma sendo executada em paralelo com outras
� Modularidade. Podemos querer construir um sistema de uma formamodular, dividindo as funções do sistema em processos ou threadsseparadas
Comunicação Inter-Processos
� Conveniência. Até mesmo um usuário individual pode trabalhar emmuitas tarefas as mesmo tempo. Por exemplo, um usuário pode estareditando, imprimindo e compilando em paralelo.
Comunicação Inter-Processos
� Modelos fundamentais de comunicação entre processos:� Memoria compartilhada. Uma região da memória que é
compartilhada pelos processo é estabelecida. Os processos podem ,trocar informações pela leitura ou escrita de dados para a regiãocompartilhada
� Troca de mensagem. A comunicação ocorre por meio de mensagenstrocadas entre os processos coomperativos
Comunicação Inter-Processos
� Os dois modelos de comunicação são mostrados abaixo:
Passagem de Mensagem Memória compartilhada
Comunicação Inter-Processos
� Os processos cooperativos precisam de mecanismos decomunicação entre processos (inter process communications� IPC), que permite a troca de dados e informações.
Comunicação Inter-Processos
� Condições de disputa (race conditions)� Processos que trabalham em conjunto podem
compartilhar algum armazenamento em comum, do qualcada um pode ler e escrever
Condições de Corrida
� Situação onde dois ou mais processos estão acessando dados compartilhados ao mesmo tempo
...
Documento 1
Documento 2
Documento 3
...
4
5
6
7
Out = 4
In = 7void printifle (file *name) {pos p = get_next_slot();print(name, p);set_next_slot(++p);
}
Preempção
Comunicação Inter-Processos
� Situação 1� Spool de impressão (fila de documento a serem impressos)
� O diretório de spool tenha um grande numero de vagasnumeradas, cada uma capaz de conter um nome dearquivo.
� Existem duas variáveis compartilhadas:
� in aponta para próxima entrada livre no spool ondeo próximo arquivo a ser impresso esta armazenado.
� out aponta para o nome do próximo arquivo a serimpresso.
Comunicação Inter-Processos
� Situação 1� Em um determinado momento as vagas 0 a 3 estão vazias.
� As vagas 4 a 6 estão preenchidas.
� Em um determinado momento os processos A e B decidemcolocar um arquivo na fila de impressão (Figura 2.16).
� O processo A lê a variável in e armazena o valor 7 navariável local chamada de proxima_vaga_livre.
� Nesse momento ocorre um interrupção.
� O processo B lê a variável in e armazena o valor 7 navariável local chamada de proxima_vaga_livre.
Comunicação Inter-Processos
� Situação 1� Nesse instante, ambos os processo pensam que a próxima
vaga disponível é a 7;
� O processo B prossegue a execução. Armazena o nome deseu arquivo na vaga 7 e atualiza in para 8.
� O processo A volta a executar e encontra o valor 7 emproxima_vaga_livre e escreve o nome do arquivo na vaga.7, apagando o nome do arquivo que o processo B gravou.
� O diretório de spool esta consistente.
� O processo B ficará aguardar sua impressão eternamente.
Comunicação Inter-Processos
Comunicação Inter-Processos
� Situação 2� Considere 2 trechos de código em C que compartilham
� O que vai ocorrer se houver uma troca de contexto quandoo processo 1 for executar a linha 2 e o processador forexecutar o processo 2?
Processo1 Processo 2
while (count == SIZE)// espero para executar
count ++;Buffer[in] = item
in (in + 1) % SIZE;
while (count ==0);// espero para executar
count--; item =buffer[out]
out = (out+1) % SIZE;
Comunicação Inter-Processos
� Regiões críticas� O que fazer para evitar a condição de disputa ?
� A solução é encontrar algum modo de impedir que mais de umprocesso utilize qualquer recurso compartilhado, que pode ser o de lere escrever ao mesmo tempo na memória compartilhada por exemplo.
� Exclusão mutua� É o modo de assegurar que outros processos sejam impedidos de usar
uma variável ou um arquivo compartilhado que já estiver em uso porum processo.
� No exemplo anterior o processo B começou a usar uma das variáveiscompartilhadas antes que o processo A terminasse de usá-la.
Exclusão Mútua
� Uma maneira de nos certificarmos de que, seum processo está acessando um recursocompartilhado, outros processos serãoimpedidos de fazê-lo
� Região Crítica: Parte do programa que acessarecursos compartilhados
� Para garantir a exclusão mútua, devemosevitar que mais de um processo esteja em suaregião crítica ao mesmo tempo
Exclusão mútua
Os mecanismos que implementam a exclusão mútua utilizam
protocolos de entrada e saída da região crítica
Exclusão Mútua
� Essa solução dificulta a cooperação de processos que utilizamdados compartilhadas na solução de um problema. Énecessário outras considerações:
� Dois ou mais processo não podem estar simultaneamente dentro desuas regiões críticas correspondentes.
� Nenhuma consideração pode ser feita a respeito da velocidade relativados processos, ou a respeito do numero de processadores do sistema.
� Nenhum processo que esteja rodando fora de sua região crítica podebloquear a execução de outro processo.
� Nenhum processo pode ser obrigado a esperar indefinidamente paraentrar em uma região crítica.
Exclusão Mútua com espera ociosa
Estratégias para obter a exclusão mútua entre processos emrelação a uma região compartilhada:
1. Inibição das interrupções. É a solução mais simples� Onde cada processo deve inibir as interrupções logo após entrar em
uma região crítica.� Habilitando-as imediatamente antes de sair dela.� Dessa forma evitamos as interrupções de relógio e
consequentemente os problemas gerados pelo escalonamento deprocessos.
� O problema dessa abordagem é o de dar a processos usuários o poder dedesabilitar interrupções, o uso indevido poderia causar problemas. Estaestratégia não é apropriada para garantir a exclusão mutua.
Exclusão Mútua com espera ociosa
2. Variáveis de travamento e impedimentos (lock variables).Nesta estratégia existe uma variável compartilhada,denominada de variável de travamento� cujo valor inicial é 0 (zero).� Ao desejar entrar em uma região crítica, o processo incialmente deve
verificar o valor da variável de travamento.� Se o valor de lock for 0, o processo altera seu valor para 1 e entra na
região critica.� Se o valor de lock for 1, o processo esta impedido de entrar na região
crítica e, portanto, deve esperar até que o lock volte para o valor 0,liberando o acesso à região critica.
Exclusão Mútua com espera ociosa
� O problema dessa estratégia é:� um processo P1 lê o valor de lock, que esta 0.� O processo é então, antes de alterar o valor para 1.� O processo p2 lê o valor lock e muda para 1, podendo entrar em sua
RC.� O processo P2 é interrompido e a execução volta para P1 que coloca
lock em 1 e entra na RC.� Nesse momento P1 e P2 estão na RC (região crítica).
Exclusão Mútua com espera ociosa
3. Escrita alternada ou chaveamento obrigatório. Nessaestratégia uma variável estabelece de quem é a vez de entrarna região critica.� Inicialmente o valor da variável vez é 0.� O processo 0 inicial e execução entrando na RC.� O processo P1 tenta entrar na RC e verifica o valor que o valor de vez é
diferente de 1, ficando bloqueado, aguardando que ela se torne 0 ecom isso ter acesso a RC.
� O tempo de verificação e processamento de P1 é chamado de esperaocupada (busy waiting)
� Ao sair da RC o processo 0 altera o valor de vez para 1 e libera o acessoà RC para o processo 1.
Exclusão Mútua com espera ociosa
� O problema nessa estratégia é que um processo pode ser impedido deentrar na RC mesmo o outro estando fora da RC.
Processo1 Processo 2
while (TRUE)while (vez != 0)
regiao_critica();vez = 1;
região_nao_critica ();
while (TRUE)while (vez !=1)
regiao_critica();vez = 0;
região_nao_critica ();
Exclusão Mútua com espera ociosa
4. Solução de Peterson. É uma técnica de se obter exclusãomutua sem a obrigatoriedade da alternância citadaanteriormente. A solução é restrita a dois processos quealternam a execução entre suas seções criticas e as seçõesrestantes.� Suponha que as instruções LOAD e STORE sejam indivisíveis; ou seja,
não podem ser interrompidas.
� Os dois processos compartilham duas variáveis:
� int turn; Boolean flag[2]
� A variável turn indica de quem é a vez de entrar na seção crítica.
� O array flag é usado para indicar se um processo está pronto para entrar na seção crítica. flag[i] = true implica que o processo Pi está pronto!
Exclusão Mútua com espera ociosa
Exclusão Mútua com espera ociosa
� A variável turn indica de quem é a vez de entrar em sua regiãocrítica.
� Se turn == i, então o processo Pi tem permissão para executarsua região critica.
� O array flag é usado para indicar se um processo está prontopara entrar em sua região critica.
� Se Flag[i] for verdadeiro, esse valor indica que o processo Pi,está pronto para entrar em sua região critica.
Exclusão Mútua com espera ociosa
Exclusão Mútua com espera ociosa
� Funcionamento da solução� Inicialmente nenhum processo esta em sua região critica.� O processo 0 chama enter_region, manifesta seu interesse escrevendo
em seu elemento do arranjo interested e põe a variável turn em 0.� Como o processo 1 não esta interessando, enter_region retorna
imediatamente.� Se o processo 1 chamar enter_region, ele ficara suspensa ali até que
interested[0] vá para FALSE, um evento que ocorre somente quando oprocesso 0 chamar leave_region para sair de sua região crítica
Problemas da Sincronização
� Velocidade de Execução dos Processos� A velocidade de execução dos processos pode interferir
em uma boa solução para o problema de exclusão mútua� Um processo mais rápido que queira acessar sua região
crítica pode ficar muito tempo parado, por estaresperando por um processo mais lento.
Problemas da Sincronização
� Starvation� Starvation é a situação onde um processo nunca consegue
executar sua região crítica e, consequentemente, acessar oseu recurso compartilhado.
� Isto pode acontecer, por exemplo, quando um processotem baixa prioridade em relação aos outros, queconcorram pelo mesmo recurso.
Problemas da Sincronização
� Sincronização Condicional� Necessária quando um recurso compartilhado não se
encontra pronto para ser utilizado pelos processos� Nesse caso, o processo que deseja acessar o recurso
deverá ser colocado no estado de espera, até o recursoficar pronto para o processamento
� Esse tipo de sincronização é chamado sincronizaçãocondicional
Problemas de Sincronização
� Inversão de Prioridades� Ocorre quando um processo de baixa prioridade entra na
região crítica
� Por causa de sua baixa prioridade, este processo nuncaganha a CPU
� Demais processos de alta prioridade não têm acesso àregião crítica
Problema do Produtor-Consumidor
� Dois processos compartilham um buffer de tamanho fixo
� Um deles (produtor) coloca informações no buffer
� O outro (consumidor) as lê e retira do buffer
Processogravador
Processoleitor
dado
Sincronização
leitura
gravação
Buffer
Problema do Produtor-Consumidor
Sleep e Wake Up
� sleep() causa o bloqueio da tarefa
� wake(proc) acorda um processo
� Sinal enviado para acordar um processo que ainda não está dormindo é perdido
� Sujeito a deadlock
Sleep e Wake Up
void produtor() {while(1) {item it;it = produz_item();if (cont == N)
sleep();grava_item(it);cont++;if (cont == 1)
wake(consumidor);}
}
void consumidor() {while(1) {item it;if (cont == 0)
sleep();item it;it = remove_item();cont--;if (cont == N-1)
wake(produtor);consome_item(it);
}}Preempção
Problema do Produtor-Consumidor
� Problema se origina quando o produtor quer colocar um novoitem no buffer, mas ele esta cheio.
� A solução é por o produtor para dormir e só desperta-loquando o consumidor remover um ou mais itens.
� Se o consumidor quiser remover um item do buffer eperceber que esta vazio, ele dormirá até que o produtorponha algo no buffer e o desperte.
� Para manter o controle é necessário uma variável do tipocount.
� Partindo da premissa que o numero de itens é N.
Problema do Produtor-Consumidor
� O produtor verificará se o valor da variável count é N.
� Se for N o produtor dormirá
� Se não for N o produtor adicionará um item e incrementara ovalor de count.
� O consumidor verifica se o valor da variável count é 0.
� Se for 0 o consumidor dormirá
� Se não for 0 o consumidor o consumidor removerá um item edecresce o valor de count em 1.
� Os processos (consumidor e produtor) também testam se ooutro deveria estar acordado e, em caso afirmativo, odesperta.
Problema do Produtor-Consumidor
� A condição de disputa pode ocorrer já que o acesso ao counté irrestrito.
� O buffer esta vazio e o consumidor lê a variável count paraverificar se o seu valor é 0.
� O escalonador decide parar de executar o consumidor.
� O escalonador começa a executar o produtor.
� O produtor insere um novo item no buffer e incrementa avariável count .
� Inferindo que o valor de count era 0 e que o consumidordeveria ir dormir, o produtor chama wakeup para acordar oconsumidor
Problema do Produtor-Consumidor
� O consumidor não esta logicamente adormecido.
� O sinal para acordar é perdido.
� Na próxima vez que o consumidor executar, testará o valor decount anteriormente lido por ele.
� Verificará que o valor 0 é dormirá.
� Mais cedo ou mais tarde o produtor preenchera o buffer etambém dormirá.
� Ambos dormirão para sempre.
Problema do Produtor-Consumidor
� Uso de Semáforos para solucionar o problema� Dijkstra introduz um variavel para conter o numero de
sinais salvos para uso futuro, um semáforo poderia contero valor 0� indicando que nenhum sinal de acordar foi salvo
� ou algum valor positivo se um ou mais sinais de acordarestivessem pendentes.
� Cria duas operações sobre o semáforo:� Down verifica se o valor é maior que 0.
� Se for, decrementa o valor (isto é, gasta um sinal de acordararmazenado) e prosseguira.
� Se o valor for 0
� O processo será posto para dormir, sem terminar o down
Problema do Produtor-Consumidor
� O processo será posto para dormir, sem terminar o down .
� Up incrementa o valor de um dado semáforo.
� Se um ou mais processos estivessem dormindo naquele semáforo,um deles seria escolhido pelo sistema.
� E seria dada a permissão para terminar o down
� Portanto, depois de um up em um semáforo com processosdormindo nele, o semáforo permanecera com 0, mas haverá umprocesso a menos dormindo nele.
� A operação de incrementar o semáforo e acordar um processo éindivisível.
� Um processo nunca é bloqueado fazendo um wakeup
Semáforos Resumo
� Introduz duas operações: UP e DOWN
� E um novo tipo de variável: o mutex (mutual exclusion)
� Mutexes são adequados apenas para gerencia a exclusãomutua de algum recurso ou parte de código compartilhado;
� Operações up e down incrementam e decrementam o mutex,respectivamente
� Processo que executa down quando o mutex está em 0 ébloqueado
� Só volta a executar quando um up é feito naquele mutex
Semáforos Resumo
� Faz uso da instrução TSL.
� Resolve o problema do sleep / wake up.
� Problema: dificuldade de programação.
Semáforos
void produtor() {while(1) {item it;it = produz_item();down(&empty);down(&mutex); grava_item(it);up(&mutex);up(&full);
}}
void consumidor() {while(1) {item it;if (cont == 0)
sleep();item it;it = remove_item();cont--;if (cont == N-1)
wake(produtor);consome_item(it);
}}
#define N 100semaforo mutex = 1;semaforo empty = N;semaforo full = 0;
Fila de esperade processos
Processo acessaa região crítica
Processo deseja entrarna região crítica
DO
WN
(S=0)
DOW
N (S
>0)
UP (S) - processo saida região crítica
Libera processoda fila de espera
Semáforos
Produtor Consumidor em C
#include <stdio.h>#include <pthreah.h>#define MAX 1000000000 /* quantos numero produzir */pthread_mutex_t the_mutexphread_cond_t codc, condp; /* usado para sinalização */int buffer = 0; /* buffer usado entre produtor e consumidorvoid * producer(void * ptr){ int i;
for (i = 1; i < MAX; i++) {pthread_mutex_lock(&the_mutex) /* obtem acesso exclusivo ao buffer */while (buffer != 0)
pthread_cond_wiat(&condp, &the_mutex);buffer = i; /* insere um item no buffer */pthread_cond_signal(&condc); /* acorda consumidor */pthread_mutex_unlock(&the_mutex); /* libera acesso ao buffer */}pthread_exit(0);
}
Produtor Consumidor em C
void * consumer(void * ptr){
int i;
for (i = 1; i < MAX; i++) {pthread_mutex_lock(&the_mutex) /* obtem acesso exclusivo ao buffer */while (buffer == 0)
pthread_cond_wait(&condc, &the_mutex);buffer = 0; /* retira um item no buffer */pthread_cond_signal(&condc); /* acorda produtor */pthread_mutex_unlock(&the_mutex);/* libera acesso ao buffer */}
pthread_exit(0);
}
Produtor Consumidor em C
int main( int argc , char ** argv){
pthread_t pro, con;pthread_mutex_init(&the_mutex,0);pthread_cond_init(&condc, 0);pthread_cond_init(&condp, 0);pthread_create(&con, 0, consumer, 0);pthread_create(&pro, 0, consumer, 0);pthread_join(pro, 0);pthread_join(con, 0);pthread_cond_destroy(&condc);pthread_cond_destroy(&condp);pthread_mutex_destroy(&the_mutex);
}
Produtor Consumidor em Java
// Classe Consumidor.javapublic class Consumidor extends Thread {
private ObjetoBuffer um_Buffer;private Semaforo s1,s2;// Construtores do Consumidor thread objectpublic Consumidor( ObjetoBuffer dado ){
super( "Consumidor" );um_Buffer = dado;
}public Consumidor( ObjetoBuffer dado, Semaforo sem1, Semaforo sem2 ){
super( "Consumidor" );um_Buffer = dado;s1 = sem1;s2 = sem2;
}// Thread Consumidor lerah o buffer 10 vezes em intervalos aleatorios
Produtor Consumidor em Java
public void run(){ int valor, soma = 0;
do {// dorme por um intervalo aleatoriotry { Thread.sleep( (int) ( Math.random() * 3000 ) );}// Tratamento de excecaocatch( InterruptedException exception ) {
System.err.println( exception.toString() );}s2.P(); // bloqueio da thread consumidoravalor = um_Buffer.lerBuffer();s1.V(); // liberacao do threads produtorasoma += valor;
} while ( valor != 10 );System.err.println(
getName() + " terminou de consumir. Totalizou: " + soma);}
} // fim da classe Consumidor
Produtor Consumidor em Java
// Classe ObjetoBuffer.javapublic class ObjetoBuffer {
private int memoria;// metodo de escrita de dados na memoriapublic void escreveBuffer( int valor ){
System.err.println( Thread.currentThread().getName() +" produzindo o valor: " + valor );
this.memoria = valor;}// metodo de leitura de dados na memoriapublic int lerBuffer(){ System.err.println( Thread.currentThread().getName() +
" consumindo o valor: " + this.memoria );return this.memoria;
}} // fim da classe ObjetoBuffer
Produtor Consumidor em Java
// Classe Principal.java// mostra duas threads modificando um objeto compartilhado.public class Principal {
// execute applicationpublic static void main( String args[] ){
ObjetoBuffer umBuffer = new ObjetoBuffer();Semaforo s1 = new Semaforo(1); // semaforo do produtorSemaforo s2 = new Semaforo(0); // semaforo do consumidor// criacao das threadsProdutor umProdutor = new Produtor( umBuffer,s1,s2 );Consumidor umConsumidor = new Consumidor( umBuffer,s1,s2);// start threadsumProdutor.start();umConsumidor.start();
}} // fim da classe Principal
Produtor Consumidor em Java
// classe Produtor.java// Definicao da classe Produtorpublic class Produtor extends Thread {
private ObjetoBuffer o_Buffer;private Semaforo s1,s2;// construtores da Thread Produtorpublic Produtor( ObjetoBuffer dado ){
super( "Produtor" );o_Buffer = dado;
}public Produtor( ObjetoBuffer dado, Semaforo sem1, Semaforo sem2 ){
super( "Produtor" );o_Buffer = dado;s1 = sem1;s2 = sem2;
}// Thread do Produtor escreverah 10 vezes no buffer em intervalos de tempo aleatorios
Produtor Consumidor em Java
public void run(){
for ( int i = 1; i <= 10; i++ ) {// dorme por um tempo aleatoriotry {
Thread.sleep( ( int ) ( Math.random() * 3000 ) );}// tratamento de excecaocatch( InterruptedException exception ) {
System.err.println( exception.toString() );}// chama metodo do objeto buffer s1.P(); o_Buffer.escreveBuffer( i );s2.V();
}System.err.println(getName() + " terminou de produzir");
}} // FIM DA CLASSE Produtor
Produtor Consumidor em Java
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=Autor.....: Marlos Andre MarquesProfessor.: Luiz Affonso=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/final class Semaforo {private int valor; //valor do semaforoprivate int esperando = 0;
//quantidade de processos bloqueados por UM DETERMINADO semaforopublic Semaforo (int i) { //construtor: inicia o semaforo adequadamente
valor = i ;} //fim do construtor
Produtor Consumidor em Java
synchronized void P() { //ou DOWN()if ( valor > 0 ) //verifica o valor do semaforo
valor--; //se semaforo maior que zero, decrementa o valor do do semaforoelse {
esperando++;//senao, incrementa o numero de threads suspensastry { wait(); } catch (InterruptedException e) { }; //senao o processo que executou a operacao P (ou DOWN) e' suspenso
esperando--;}; //fim do else/if
} //fim do metodo P()synchronized void V() { //ou UP()
if (esperando > 0) //se tem processo na fila de esperanotify(); //tira processo da fila de esperaelsevalor++; //senao, incrementa o valor do semaforo
} //fim do metodo V()} //fim da classe Semaforo
Monitores
� Para facilitar a escrita de certos programas Hoare e Hansenpropuseram uma unidade básica de sincronização, chamadamonitor.
� Um monitor é uma coleção de rotinas, variáveis e estrutura dedados, agrupadas em um tipo de módulo ou pacote
� Os processos podem chamar as rotinas em um monitorquando quiserem
Monitores
� Implementa pacotes com funções e estruturas dedados que não podem ser diretamente acessadaspelos processos.
� Garante que apenas 1 processo está dentro domonitor.
� Requer suporte do compilador.
� Funciona apenas para sistemas com memóriacompartilhada.
Declaração de
variáveis globais
Procedimentos
Fila de entrada
Inicialização
de variáveis
Proc. 1
Proc. 2
Proc. n
Monito
r
Monitores
Passagem de Mensagem
� Utiliza as chamadas send e receive.
� send(destino, mensagem).
� receive(fonte, mensagem).
� Fonte e destino podem ser processos comunicantesem máquinas diferentes.
� Permite a implementação de mailbox.
Passagem de Mensagem
void produtor() {while(1) {item it;mensagem msg;it = produz_item();receive(consumidor, &msg);constroi_msg(&msg, item);send(consumidor, &msg);
}}
void consumidor() {item it;int i;mensagem msg;for (i=0; i<N; i++)send(produtor, &msg);
while(1) {receive(produtor, &msg);it = extrai(msg);send(produtor, &msg);consome_item(it);
}}
Bibliografia
� Tanenbaum, A. S. Sistemas OperacionaisModernos, São Paulo, Pearson, 2010
� Silberschatz, A., Galvin, P.B. Fundamentos deSistemas Operacionais. 8ª Edição. São Paulo:LTC, 2010.