Processo A

Propaganda
Sistemas operacionais
Carlos Oberdan Rolim
Ciência da Computação
Sistemas de Informação
Processos
* Baseado no material do Prof. Luis Cláudio Gubert
Processos
Conceito de Processo
Escalonamento de Processos
Operações com Processos
Processos Cooperativos
Comunicação entre Processos
Conceito de processo
Um sistema operacional executa uma variedade de programas:
Sistema Batch – jobs
Sistema Tempo Compartilhado (Time-shared) – programas do usuário
ou tarefas
Livros usam os termos job e processo quase que
indeterminadamente.
Processo – um programa em execução; execução do processo
deve progredir de maneira seqüencial.
Um processo inclui:
Contador de programa
pilha
Seções de dados
Criação de processos
Sistemas operacionais precisam assegurar a criação de
todos os processos necessários
Há quatro eventos que fazem com que processos sejam
criados
Inicio do sistema
Execução de uma chamada ao sistema de criação de processo por um
processo em execução
Uma requisição do usuário para criar um novo processo
Inicio de um job em lote
Inicialização de processos em segundo plano pelo SO
Daemons
Tecnicamente um processo é criado quando um outro
processo faz uma chamada ao sistema de criação de
processos
Fork  clone identico ao processo que o chamou
Término de processos
Após efetuar sua tarefa processo termina por alguma das
seguintes razões:
Saída normal (voluntária)
Saída por erro (voluntária)
Erro fatal (involuntário)
Cancelamento por um outro processo (involuntário)  Ex.comando kill
Hierarquia de processos
Relação pai x filho de processos
No Unix um processo pai, todos os seus filhos e
descendentes formam um grupo de processos
Quando um sinal é enviado todos os processos do grupo de
processos recebem o sinal e decidem o que fazer
Exemplo de inicialização do sistema
Processo init que cria os teminais de video, que disparam os
interpretadores de comando, que disparam novos processos e assim
por diante
Init é o processo raiz
Windows não apresenta hierarquia de processos
Todos são iguais
Somente existe uma especie de hierarquia quando um processo cria
outro
Pai recebe handle dos filhos para os controla-los.Porém pode passar
esse handle para outros processo invalidando conceito de hierarquia
Estados de processo
Durante a execução de um processo, ele altera seu
estado
Novo (new): O processo está sendo criado.
Executando (running): instruções estão sendo executadas.
Esperando (waiting): O processo está esperando algum evento
acontecer.
Pronto (ready): O processo está esperando ser associado a um
procesador.
Terminado (terminated): O processo terminou sua execução.
Diagrama de estados de processos
Process Control Block (PCB)
Informações associadas com cada processo.
Estado do Processo
Contador de Programas
Registradores da CPU
Informações de escalonamento da CPU
Informação de Gerenciamento de memória
Informação para Contabilidade
Informações do status de E/S
Processo Control Block
Troca de CPU entre processos
Filas de escalonamento de processos
Fila de Job – conjunto de todos os processos no
sistema.
Fila de Processos prontos (Ready queue) – conjunto de
todos os processos residentes na memória principal,
prontos e esperando para executar.
Fila de dispositivos – conjunto dos processos
esperando por um dispositivo de E/S.
Migração de processos entre as várias filas.
Fila de processos pronto e várias filas de
E/S
Representação de Escalonamento de Processos
Escalonadores
Escalonador de Jobs (Long-term scheduler) – seleciona
quais processos devem ser trazidos para a fila de
processos prontos.
Escalonador da CPU (Short-term scheduler) – seleciona
qual processo deve ser executados a seguir e aloca
CPU para ele.
Inclusão de escalonador de nível médio
Escalonadores (cont)
Escalonador da CPU é invocado muito freqüentemente
(milisegundos) → (deve ser um fato).
Escalonador de Jobs é invocada muito infreqüentemente
(segundos, minutos) → (pode ser lento).
O escalonador de Jobs controla o grau de multiprogramação.
Processos podem ser descritos como:
Processos com E/S predominante (I/O-bound process) – gasta mais
tempo realizando E/S do que computando, muitos ciclos curtos de CPU.
Processos com uso de CPU predominante (CPU-bound process) –
gasta mais tempo realizando computações; poucos ciclos longos de
CPU.
Troca de contexto
Quando CPU alterna para outro processo, o sistema
deve salvar o estado do processo deixando o
processador e carregar o estado anteriormente salvo do
processo novo.
Tempo de troca de contexto é sobrecarga no sistema; o
sistema não realiza trabalho útil durante a troca de
contexto.
Tempo de Troca de Contexto é dependente de suporte
em hardware.
Criação de processos
Processo pai cria processo filho, o qual, por sua vez,
pode criar outros processos, formando uma árvore de
processos.
Compartilhamento de Recursos
Pai e filho compartilham todos os recursos.
Filho compartilha um subconjunto dos recursos do pai.
Pai e filho não compartilham recursos.
Execução
Pai e filho executam concorrentemente.
Pai espera até filho terminar.
Criação de processos (cont)
Espaço de endereçamento
Filho duplica espaço do pai.
Filho tem um programa carregado no seu espaço.
Exemplos no UNIX
Chamada de sistemas fork cria um novo processo
Chamada de sistemas execve é usada após o fork para
sobrescrever o espaço de memória do processo com um novo
programa.
Uma Árvore de Processos em um Sistema UNIX Típico
Terminação de processos
Processo executa última declaração e pede ao sistema
operacional para decidir (exit).
Dados de saída passam do filho para o pai (via wait).
Recursos do processo são desalocados pelo sistema operacional.
Pai pode terminar a execução do processo filho (abort).
Filho se excedeu alocando recursos.
Tarefa delegada ao filho não é mais necessária.
Pai está terminando.
Comunicação entre Processos
Processos Independentes.
Não afetam nem são afetados por outros processos.
Processos Cooperados.
Compartilham:
Memória;
Arquivos;
Dispositivos de E/S;
Etc.
Vantagens da cooperação entre processos:
Compartilhamento de Informações
Aumento na velocidade da computação
Modularidade
Conveniência
Processos Cooperados
Compartilhamento de dados.
Processo “produtor” de dados.
Insere informações no buffer
Processo “consumidor” de dados,
Remove informações do buffer
Buffer:
Limitado: Produtor e Consumidor.
Ilimitado: Somente Consumidor.
Implementação.
Via memória compartilhada;
Via IPC (Interprocess Comunication - SO)
Buffer Circular
Implementação como um array circular.
próxima
saída
próxima
entrada
4
8
5
7
6
Introdução de um contador de quantidade.
Produtor e Consumidor manipulam o contador.
Contador
5
Implementação
i aponta para posição anterior ao primeiro elemento
f aponta para último elemento
c indica o número máximo de elementos presentes
N indica o número máximo de elementos
Buffer vazio
i == f
c == 0
Buffer cheio
i == f
c ==N
Comportamento básico
int buffer[N];
int c = 0;
int i = 0, f = 0;
Produtor
while (true)
f = (f + 1) % N;
buffer[f] = produz();
c++;
Consumidor
while ( true)
i = ( i + 1 ) % N;
consome( buffer[i]);
c--;
Problemas
Produtor insere em posição que ainda não foi
consumida
Consumidor remove de posição já consumida
Condições de Corrida (Race Conditions)
Processos trocam dados, as vezes, através de memória
Principal, arquivo...
Região/seção crítica
Porção de programa que pode levar a condição de disputa
Tipo de memória não altera o problema
Alguma forma de garantir que apenas 1 esteja na região crítica
Condições de Corrida
Mecanismo de Sincronização.
Garante o compartilhamento de recursos e a comunicação entre
os processos.
Garante a integridade e a confiabilidade dos dados
compartilhados.
Condições de Corrida:
Situações onde dois ou mais processos estão acessando dados
compartilhados.
O resultado final pode variar de acordo com a ordem de
execução.
Condições de Corrida
Exemplo 1:
2
1
7
7
Processo
A
3
7+1
Processo
B 4
7-1
7
5
8
Resultado Final: Contador = 6 (ERRO!)
6
6
Condições de Corrida
Exemplo 2:
2
Processo
A
8
suspenso
recebe CPU
10
Y
5
6
1
9
7
8
próxima
entrada
4
Valor armazenado pelo
processo B3é perdido.
7
6
X
4
5
7
8
Processo
B
3
7
recebe CPU
suspenso
Condições de Corrida
Região Crítica:
Parte do código onde é feito acesso a recursos compartilhados,
e que podem levar a condições de corrida.
Ex: Processo A.
Código normal
Início da Seção Crítica (Protocolo de Entrada)
Seção Crítica
Término da Seção Crítica (Protocolo de Saída)
Código normal
Concorrência em programas
Enquanto um processo estiver usando um recurso, os
outros devem aguardar até que o recurso esteja
liberado.
Exclusão Mútua.
Exclusividade no acesso a um determinado recurso.
A exclusão mútua deve afetar os processos
concorrentes quando um deles estiver em uma região
crítica.
Regiões críticas
Como evitar condições de disputa?
Implementar exclusão mútua
Um por vez junto à região
Garantir que dois ou mais processos estarão sincronizados,
e só um dentro da região crítica
Operando sobre dados compartilhados
Regiões críticas
Quatro requisitos básicos para os algoritmos
Dois ou mais processos NUNCA podem estar simultaneamente na
região crítica
Não considerar velocidade relativas dos processos
Quem estiver fora da região não pode bloquear quem quer entrar
Tem que entrar em algum momento!
Regiões críticas
Algumas alternativas
Espera ocupada
Inibição de interrupção, variáveis de bloqueio, estrita alternância, TSL
Bloqueio/desbloqueio
Sleep/wakeup
Semáforos
Monitores
Troca de mensagens
“caixa postal”, rendezvous
Problemas de Sincronização
Velocidades muito diferentes dos processos:
Podem causar problema de solução de sincronização entre
processos.
Ex: Problema produtor / consumidor.
Starvation (Indefinitely Postponed):
Um processo nunca consegue executar sua região crítica e
acessar o recurso compartilhado.
Outros processos são sempre prioritários.
Também chamado de problema de inversão de prioridade
Soluções de Hardware
Inibição das interrupções:
Solução mais simples para a exclusão mútua;
Falha de Proteção:
O processo precisa voltar a habilitar as interrupções.
Instrução Test-and-Set.
Utilização de uma variável para testar a possibilidade de
executar a região crítica.
O processo impedido de executar sua região crítica executa um
loop de espera.
Gasto de CPU.
Inibição de interrupção
Processo desativa interrupções quando entra na região
crítica
Evita a interrupção
Ninguém, além dele, estará processando
Problemas
Usuário é não confiável
Sistemas multiprocessados
Kernel pode precisar interromper (e.g., atualizar lista de prontos)
Test and Set Locked (TSL)
Precisa de apoio do hardware
Operação para mover e ajustar de forma atômica um registrador de flag
Só entra se registrador igual a 0
entrar_regiao:
TSL
register, flag
CMP register, #0
JNZ
entrar_regiao
RET
sair_regiao:
MOV flag, #0
RET
// copiar flag em register e faz flag = 1
// register ? 0 : 0, 1
// volta para novo TSL
// retorna ao processo
Processo X {
código...
entrar_regiao()
// coloca 0 em flag
R.C.
// retorna ao processo
sair_regiao()
código...
}
Soluções de Software
Estrita alternância
Bloqueio/desbloqueio
Sleep/wakeup
Semáforos
Monitores
Troca de mensagens
“caixa postal”, rendezvous
Em geral, as soluções por software resolvem a exclusão
mútua, mas geram a espera ocupada
(Busy Wait):
Teste contínuo de uma variável até que ocorra uma mudança no seu
valor;
O processo impedido de executar sua região crítica executa um loop de
espera.
Gasto de CPU.
Estrita alternância
Cabana com uma lousa dentro
Só um na cabana, só um número na lousa
Quem quiser entrar na região, verifica a lousa
Entra na cabana. Se a lousa não tiver o seu número, sai e dá uma volta
Se estiver, entra na região e, ao sair, escreve o próximo número
Estrita alternância
Outra opção: várias cabanas, com várias lousas
Cada um examina todas as lousas mas altera apenas a sua
TRUE na lousa  processo na região
Quem quiser entrar verifica as outras lousas
Se todas falsas, escreve TRUE na sua e entra
Escreve FALSE ao sair
Vários processos
Verificação não é atomica
Sleep/Wakeup
TSL funciona, mas é espera ocupada...
Problema de prioridade invertida
L com prioridade baixa na região critica, e
H com alta prioridade tentando entrar
Starvation
Em vez de esperar, um processo comunica diretamente ao
outro
SLEEP e WAKEUP
Produtor/consumidor com buffer limitado
Buffer cheio? Produtor dorme
Buffer vazio? Consumidor dorme...
Sleep/Wakeup
Extern N, count;
#define N 100
int count = 0;
void consumer (void) {
int item;
while (TRUE) {
if (count == 0) sleep();
remove(item); count--;
if (count == N-1) wakeup (producer);
consome(item);
}
}
void producer(void) {
int item;
while (TRUE) {
produz(&item);
if (count == N) sleep();
armazena(item);
count++;
if (count == 1) wakeup(consumer);
}
}
Sleep/Wakeup
Problemas
Condição de disputa em “count”
Buffer vazio, consumidor sabe que é zero
Interrompido
Produtor produz e faz count++ e “acorda” consumidor
Consumidor volta e vai dormir
Produtor enche o buffer e vai dormir
Sinal não usado é perdido...
Adicionar um bit; sleep com bit, ignora...
Geralmente não funciona
Semáforos
Ferramenta de sincronização criada por Dijkstra
(1965);
Características:
Variável inteira;
Não negativa.
Manipulados por duas operações atômicas:
DOWN ou Wait (P - Proberen - Testar)
UP ou Signal (V - Verhogen - Incrementar)
Implementados como chamada ao sistema.
Semáforos
Dijskstra (1965)
Variável que armazena sinais para uso futuro
Novo tipo de variável: semáforo
Operações de down e up
DOWN(s) {
s --;
if (s < 0)
sleep();
}
UP(s) {
s ++;
if (s <= 0)
wakeup_alguém()
}
Operações atômicas: teste, incremento...
Semáforos (Counting Semaphores);
Semáforos Binários (Mutual Exclusion Semaphores);
Semáforos e cervejas...
Hora
03:00
03:05
03:10
03:15
03:20
03:25
03:30
03:35
03:36
03:40
03:50
03:51
03:51
Você
Chega em casa
Olha no freezer, sem cerveja
Sai para o bar
Chega no bar
Compra uma grade e sai
Chega em casa
Guarda as cervejas
Colega
Chega em casa
Olha no freezer, sem cerveja
Sai para o bar
Chega no bar
Compra uma grade e sai
Chega em casa
Guarda as cervejas
SEM ESPAÇO!!!
Semáforos e cervejas...
Hora
03:00
03:04
03:05
03:10
03:15
03:19
03:20
03:25
03:30
03:35
03:36
03:37
03:38
Você
Chega em casa
DOWN(&birita)
Olha no freezer, sem cerveja
Sai para o bar
Chega no bar
Compra uma grade e sai
Chega em casa
Guarda as cervejas
UP(&birita)
Colega
Chega em casa
DOWN(&birita)
Olha no freezer, COM cerveja
Semáforos e cervejas...
Semáforo birita iniciado com 1
Você (A)
Colega (B)
P(&birita);
Se (sem cerveja)
compra cerveja;
V(&birita);
P(&birita);
Se (sem cerveja)
compra cerveja;
V(&birita);
Execução
Antes
birita
1
A: P() 0
B: P() -1
A: V() 0
B: V() 1
fila
Você
B
RC
RC
fim
Colega
espera
pronto, RC
fim
Semáforos – Comportamento básico
down(s)
if (s == 0)
bloqueia_processo();
else s--;
up(s)
if (s == 0 && existe processo bloqueado)
acorda_processo();
else s++;
Semáforos e E/S
Cada dispositivo com seu semáforo
Início de E/S
Processo gerente faz um down
“Sleep”
Fim de E/S
Processo faz um up (libera)
“Wakeup”
Semáforos
Falsa impressão de simplicidade
Inversão da ordem de DOWNs
Buffer completo  produtor bloqueado e mutex 0
Consumidor tenta acesso ao buffer  bloqueado
Deadlock! (depois...)
Facilitar a sincronização, com primitivas de alto nível
Hoare (1974) & Hansen (1975)
Monitores
Semáforos
Semáforos fazem duas coisas
Exclusão mútua
Só um dentro
Sincronização
Um processo espera por um “sinal” de outro processo
Binário ou não
Produtor – Consumidor com Semáforo
semaforo cheio = 0;
semaforo vazio = N;
Produtor
while (true)
wait(vazio);
f = (f+1)%N;
buffer[f] = produz();
signal(cheio);
Consumidor
while(true)
wait(cheio);
i = (i+1) %N;
consome(buffer[i]);
signal(vazio);
Semáforos
#define N 100
typedef int semaphore;
semaphore mutex = 1; empty = N; full =0;
void producer(void) {
int item;
while (TRUE) {
produz(&item);
down(&empty);
down(&mutex);
armazena(item);
up(&mutex);
up(&full);
}
}
extern mutex, empty, full;
void consumer (void) {
int item;
while (TRUE) {
down(&full);
down(&mutex);
remove(&item);
up(&mutex);
up(&empty)
consome(item);
}
}
Mutex (Mutual Exclusion)
Estrutura de sincronização bastante simples que pode
estar em dois estados:
Locked;
Unlocked.
Duas operações são
definidas sobre um mutex:
Processo 1
Lock;
Unlock.
lock
unlock
lock
Mutex
unlock
Processo 2
Locks
Convenções
Lock::Obtêm() antes de acessar dados
Bloqueia se o lock não estiver disponível
Lock::Libera() depois de acessar
Erro se tentar liberar antes de obter
Processo A
Processo B
lock *birita;
extern lock *birita;
birita->obtêm();
Se (sem cerveja)
compra cerveja;
birita->libera();
birita->obtêm();
Se (sem cerveja)
compra cerveja;
birita->libera();
Variáveis condicionais
São iguais a semáforos??? Não!
Semáforos têm valor, VCs não
Um signal (V, Up) em um semáforo sempre incrementa, mesmo que
não haja pendências. Depois, em um wait (P, Down), o processo
decrementa e segue
Nas VCs, um signal sem wait simplesmente é perdido. Depois, se
houver um wait, ele vai sempre aguardar um signal, mesmo que já
tenha havido 1 bilhão de signals
Variáveis condicionais
Sleep/wakeup são a mesma coisa? Quase
Sleep/wakeup se aplicam a processos e threads específicas, e não a
variáveis
Monitores
Mecanismo de sincronização de alto nível
proposto por Hoare (1974) e Brinch Hansen
(1975);
Conjunto de procedimentos e funções de alto nível
agrupadas em um módulo
Similar a uma classe, na OO
Característica mais importante é a
implementação automática da exclusão mútua:
Somente um processo pode estar ativo em um monitor em um
determinado instante de tempo.
Somente um procedimento sendo executado, até a completude, por vez
Programador livre de especificar as restrições
Monitores
Compilador tem que oferecer suporte a monitores
Chamadas aos procedimentos do monitor com certas “regalias”
Se algum outro processo estiver ativo no monitor, suspende o novo
processo
Geralmente implementados com o uso de semáforos binários
Poucas linguagens implementam (e.g., ADA)
Monitores
Idéia similar a um objeto
Alterar propriedades, só através dos métodos
Entrar na região crítica, só através do monitor
Monitores e semáforos
Dependem de memória comum
Em memória distribuída a coisa não funciona
Como “compartilhar” uma variável?
Troca de mensagens
Primitivas de SEND/RECEIVE
Enviar para e receber de
Recepção bloqueante
Novos problemas
Perda de mensagens
ACK, NACK
Recebimento duplicado
Controle de seqüência
Segurança...
Troca de mensagens
Produtor/consumidor
Consumidor
Produtor
enviar N msg vazias
while (TRUE) {
receive (produtor, &m);
extrai_item();
send (produtor, &m);
consome_item();
}
while (TRUE) {
produz_item();
receive (consumidor, &m);
constroi_msg();
send (consumidor, &m);
}
Troca de mensagens
Diretamente com sockets
Plataformas de portabilidade
PVM, MPI, Linda, P4, Parmacs...
Caixa postal e rendevouz
SEND/RECEIVE assíncrono
Só bloqueia com caixa postal cheia
Buffer (CP) finito
SEND/RECEIVE síncrono
Bloqueia até entregar
Mais fácil de implementar
Caixa postal e pipes
Pipe são caixas postais
Fronteiras de mensagens não existem
Emular com leitura por tamanho fixo
Threads
Uma thread (ou um processo leve) é uma unidade básica de
utilização da CPU; ela consiste de:
Contador de programas
Conjunto de registradores
Espaço de pilha
Uma thread compartilha com seus pares (outras threads
vinculadas):
Seção de código
Seção de dados
Recursos do sistema operacional
Coletivamente conhecida como uma tarefa (task).
Um processo tradicional ou pesado é igual a uma tarefa com
uma thread
Threads (cont)
Em uma tarefa com múltiplas threads, enquanto uma thread servidora
está bloqueada e esperando, uma segunda thread na mesma tarefa
pode executar.
Cooperação de múltiplas threads no mesmo job traz alta vazão (throughput) e
aumento de desempenho.
Aplicações que requerem compartilhamento de um buffer comum (p.ex.:
produtor-consumidor) se beneficiam da utilização de threads.
Threads provêem um mecanismo que permite a processos
seqüenciais realizarem chamadas de sistemas bloqueantes enquanto
podem ao mesmo tempo explorar o paralelismo.
Threads suportadas pelo Kernel (Mach e OS/2).
Threads em nível de usuário; suportadas acima do kernel, via um
conjunto de chamadas de bibliotecas no nível do usuário (Projeto
Andrew do CMU).
Abordagem híbrida implementa tanto threads em nível do usuário
quanto suportadas pelo kernel (Solaris 2).
Múltiplas Threads
Suporte a threads no solaris 2
Solaris 2 é uma versão de UNIX com suporte a threads nos
níveis do usuário e do kernel, suporte a multiprocessamento
simétrico e escalonamento em tempo real.
LWP (processos leves) – nível intermediário entre threads no
nível do usuário e do kernel.
Necessidades de recursos para cada tipo de thread:
Kernel thread: pequenas estruturas de dados e uma pilha; troca de
contexto entre threads não requer alteração em informações acessadas
pela memória – relativamente rápidas.
Processos leves (LWP): PCB com dados de registradores, informações
de contabilidade e de memória; troca de contexto entre LWP é
relativamente lenta.
Thread em nível de usuário: somente necessita de pilha e contador de
programa; não havendo envolvimento do kernel tem-se uma troca de
contexto rápida. Kernel somente enxerga os LWPs que suportam
threads em nível de usuário.
Threads no solaris
Comunicação entre processos (IPC)
Mecanismo para processos se comunicarem e sincronizarem suas
ações.
Sistema de mensagens – processos se comunicam uns com os outros
sem utilização de variáveis compartilhadas.
Suporte a IPC provê duas operações uma para envio outra para
recebimento:
send(mensagem) – tamanho da mensagem fixo ou variável
receive(mensagem)
Se P e Q querem se comunicar, eles necessitam:
Estabelecer um link de comunicação entre eles
Trocar mensagens via send/receive
Implementação de links de comunicação
Físico (ex. Memória compartilha, barramento de hardware)
Lógico (ex. Propriedades lógicas)
Questões de implementação
Como são estabelecidas as ligações?
Pode um link estar associado com mais de dois processos?
Quantos links podem existir entre cada par de processos
comunicantes?
Qual a capacidade de um link?
O tamanho da mensagem utilizado pelo link é fixo ou variável?
O link é unidirecional ou bidirecional?
Comunicação direta
Processos devem nomear o outro explicitamente:
send (P, mensagem) – envia uma mensagem ao processo P
receive(Q, mensagem) – recebe uma mensagem do processo Q
Propriedades dos links de comunicação
Links são estabelecidos automaticamente.
Um link é associado com exatamente um par de processos
comunicantes.
Entre cada par de processos existe exatamente um link.
O link pode ser unidirecional, mas é usualmente
bidirecional.
Comunicação indireta
Mensagens são dirigidas e recebidas de caixas postais – mailboxes
(também chamadas de portas).
Cada mailbox possui uma única identificação.
Processos podem se comunicar somente se eles compartilham a mailbox.
Propriedades do link de comunicação:
O link é estabelecido somente se os processos compartilham uma mailbox
comum
Um link pode estar associado com muitos processos.
Cada par de processos pode compartilhar vários links de comunicação.
Link pode ser unidirecional ou bidirecional.
Operações
Criar uma nova mailbox
Enviar e receber mensagens através da mailbox
Destruir uma mailbox
Comunicação indireta (cont)
Compartilhamento de Mailbox
P1, P2, e P3 compartilham mailbox A.
P1, envia; P2 e P3 recebem.
Quem recebe a mensagem?
Soluções:
Permitir que um link esteja associado com no máximo dois
processos.
Permitir somente a um processo de cada vez executar uma
operação de recebimento.
Permitir ao sistema selecionar arbitrariamente por um receptor.
Remetente é notificado de quem foi o receptor.
Bufferização
Fila de mensagens associada ao link; implementada
em uma dentre três formas.
Capacidade Zero – 0 mensagens
Remetente deve esperar pelo receptor (rendezvous).
Capacidade Limitada – tamanho finito de n mensagens
Remetente deve aguardar se link está cheio.
Capacidade Ilimitada – tamanho infinito
Remetente nunca espera.
Condições de exceção – Recuperação de
error
Término de processos
Perda de Mensagens
Embaralhamento de Mensagens
Download