Buscar

coulouris-sistemas-distribuidos-cap5-6

Prévia do material em texto

1 SD Cap. 5-6 1 SD Cap. 5-6 
Cap. 5 – Objetos Distribuídos e 
Invocação Remota 
 
Aplicação distribuída: conjunto de processos que cooperam entre si; 
• Precisam invocar operações em processos remotos para realizar 
serviços. 
Modelos de programação usados: 
• Chamada de procedimentos: extendida no RPC para permitir a 
chamada de procedimentos remotos; 
• Invocação de métodos: extendida no RMI para permitir a 
invocação de métodos em objetos remotos; 
• Programação orientada a eventos: permite a objetos receber 
notificações de eventos em objetos onde registraram interesse. 
Extendida para permitir notificação sobre eventos distribuídos. 
 
Middleware 
 
Aplicações 
RMI, RPC e eventos 
Protocolo request – reply 
Representação externa de dados 
Sistema operacional 
 
Aspectos importantes: 
• Transparência de localização: no RPC, quem chama uma 
função não sabe se ela é local ou não, se roda no mesmo 
processo ou num diferente. Se for remota, não se sabe onde está 
o processo que vai ser executado. Recebendo um evento 
distribuído, o processo não sabe onde está o processo que o 
gerou. 
• Protocolos: são independentes do sistema de comunicação 
básico. 
• Diferenças de hardware: são encobertas por operações de 
marshalling com EDR. 
• Sistema operacional: a aplicação que usa o middleware não 
depende do SO local. 
• Linguagens diferentes: alguns middlewares permitem 
independência de linguagem. Um objeto escrito numa linguagem 
pode invocar métodos em objetos escritos em outra. 
 
5.1.1 Interfaces 
 
Na programação por módulos, o relacionamento entre módulos é 
feito via uma interface. Nela, relaciona-se quais métodos estão 
disponíveis para acessar determinado módulo. 
Enquanto a interface permanecer igual, o acesso ao módulo não é 
alterado, mesmo que a implementação mude. 
 
Interfaces em SDs 
 
Num programa distribuído, um módulo não pode acessar variáveis 
de outro. 
A interface de um módulo não pode especificar acesso a variáveis. 
O IDL do CORBA permite especificar atributos, mas o acesso não é 
direto. A plataforma insere funções de consulta e atualização de 
variáveis automaticamente. 
Middleware 
2 SD Cap. 5-6 2 SD Cap. 5-6 
Os mecanismos de passagem de parâmetros das chamadas locais não 
se aplicam em programas distribuídos (passagem por valor ou por 
referência). 
Na interface, a especificação de parâmetros indica apenas input e/ou 
output: 
• Input: parâmetros passados para a função invocada que 
fornecem valores para o seu algoritmo; 
• Output: parâmetros que recebem resultados da função 
invocada. 
Ponteiros não podem ser usados em invocações de funções. 
 
Diferença entre RPC e RMI: 
• Interface de serviço: conjunto de funções disponíveis para 
acessar os serviços de um servidor no modelo cliente-servidor; 
• Interface remota: métodos de um objeto disponíveis para 
invocação por outros objetos; 
o Define parâmetros e forma de acesso; 
o Aceita passagem de objetos como argumentos; 
o Permite passagem de referências para objetos. 
 
5.2 Comunicação entre objetos 
distribuídos 
5.2.1 Modelo de Objetos 
 
Exceções 
 
Tipos de erros que um processo pode encontrar durante sua 
execução: 
• Erros controláveis: valores inconsistentes de argumentos, falha 
em encontrar um dado num BD, etc. 
• Erros externos: falha em acessar arquivos ou sockets, etc. 
• Erros internos: divisão por zero, endereços de memória 
inválidos, etc. 
• Erros de dependência: ocorrem em processos hierarquicamente 
superiores. 
 
O modelo de objetos permite colocar tratamento de erros através de 
comandos throw. Isso evita que o programador insira todos os testes 
no meio do código de um serviço. 
O tratamento é colocado em blocos separados e a execução desvia 
para esses blocos quando um evento é catched pelo programa. 
 
Garbage collection 
 
Objetos ocupam espaço e devem ser liberados quando não são mais 
necessários. 
Algumas linguagens (ex. Java) possuem mecanismos para liberar 
objetos quando não são mais referenciados. 
Outras não possuem e obrigam o programador a fazer esse controle 
(ex. C++). Operação sujeita a erros. 
 
5.2.2 Objetos distribuídos 
 
Objetos distribuídos podem se organizar de várias formas. 
A invocação de seus métodos segue modelos previamente estudados. 
3 SD Cap. 5-6 3 SD Cap. 5-6 
Um dos pontos importantes é verificar se um determinado objeto (ou 
método) pode ser invocado concorrentemente (+ de uma invocação 
no mesmo intervalo – uma invocação feita antes da anterior ser 
executada). 
O fato de que os dados de um objeto são acessados apenas pelos 
seus métodos permite aplicar técnicas de controle: 
• Ex.: Java - métodos sinchronized; 
• Objetos podem ser copiados para caches locais, sendo acessados 
diretamente; 
• Invocação via RMI permite acesso ao mesmo objeto por 
plataformas diferentes – possíveis conversões são feitas por 
EDR. 
 
5.2.3 O modelo de objetos distribuídos 
 
Tipos de invocação: 
• Local: feitas dentro do mesmo processo; 
• Remota: feita entre processos diferentes – podem residir ou não 
em máquinas diferentes. 
 
Para ser acessado remotamente, um objeto deve ter uma referência 
remota. 
Cada objeto remoto deve ter uma interface remota, que especifica 
quais dos seus métodos podem ser acessados remotamente. 
 
Referência a objeto remoto 
 
Identificador que permite acessar um objeto remotamente. 
É único no sistema inteiro e permite identificar um objeto 
determinado, independente de sua localização. 
Seu formato é diferente de uma referência local. 
Referências remotas podem ser passadas como argumentos. 
 
Interfaces remotas 
 
A classe de um objeto remoto implementa os métodos de sua 
interface remota. 
Outros objetos só podem invocar métodos de um objeto que 
pertencem a sua interface remota. 
 
5.2.4 Quetões de projeto para RMI 
 
Diferenças entre chamadas locais e remotas: 
• Chamadas locais são executadas exatamente 1 vez; sobre 
chamadas remotas já não é sempre assim; 
• O nível de transparência do RMI precisa ser definido. 
 
Semânticas de invocação RMI 
 
Escolhas sobre protocolos request-reply: 
• Mensagens retry: até quando retransmitir uma requisição, antes 
de receber a resposta ou assumir que o servidor falhou; 
• Filtro de duplicados: com a possibilidade de retransmissões, se 
o servidor deve usar um filtro; 
• Retransmissão de resultados: se um histórico deve ser mantido 
em vez de re-executar sempre cada comando; 
 
4 SD Cap. 5-6 4 SD Cap. 5-6 
Medidas de tolerância a falhas 
Retransmitir 
requisições 
Filtro de 
duplicados 
Re-executar ou 
retransmitir 
reply 
 
Semânticas de 
invocação 
Não Não aplicável Não aplicável Maybe 
Sim Não Re-executar At-least-once 
Sim Sim Retransmite At-most-once 
 
Obs.: para invocação de métodos locais, a semântica é exactly-once! 
 
Transparência 
 
No RPC, certas atividades (marshalling, envio de mensagens, 
retransmissão da requisição após um timeout) são escondidas do 
programador e realizadas de forma transparente. 
Com objetos distribuídos, isso é extendido para localizar e contactar 
objetos remotos. 
 
Invocações remotas são diferentes das locais porque envolvem 
redes. Pode haver falhas de rede ou máquina sem que se possa 
distinguir uma da outra. 
A grande questão é se a máquina destino recebeu a msg e se 
conseguiu executá-la. 
Isso obriga os objetos remotos a tratamentos para recuperação de 
cada caso. 
 
O atraso de uma invocação remota é enorme comparado a uma 
operação local. Então, é interessante minimisar esse custo. 
Apesar de se procurar por transparência, é interessante que a 
diferença entre invocações locais e remotas sejam explícitas, já que 
as implicações são grandes. 
Ex.: 
• Corba repassa ao programa erros de comunicação como exceção; 
• A IDL também permite especificar o tipo de semântica que se 
deseja – isso informa o projetista sobre que tipo de operação o 
objeto deve realizar; 
• Java RMI separa invocações locais de remotas. 
 
5.2.5 Implementação de RMI 
 
Módulo de comunicação 
 
• Executao protocolo request-reply; 
• Especifica tipo de msg, requestId, referência remota; 
• Determina a semântica; 
• No servidor, seleciona o dispatcher. 
 
Módulo de referência remota 
 
• Tradução entre referências remotas e locais; 
• Cria referências remotas; 
• Mantém uma tabela de objetos remotos: 
o Entradas para todos os objetos remotos relacionados ao 
processo; 
o Entradas para cada proxy local. 
 
5 SD Cap. 5-6 5 SD Cap. 5-6 
Software RMI 
 
Camada entre objetos da aplicação e módulos de comunicação e 
referência remota. 
Função de seus componentes: 
• Proxy: 
o Torna transparente para o cliente as invocações 
(comporta-se como um objeto local, mas repassa as 
invocações para os objetos remotos); 
o Esconde detalhes da referência remota, marshalling, 
unmarshalling, envio e recepção de msgs; 
o Um proxy para cada objeto remoto que o processo usa. 
• Dispatcher: 
o Servidores possuem um dispatcher e um skeleton para 
cada classe de objetos remotos; 
o Recebe requisições; methodId diz que método deve ser 
chamado; passa a requisição. 
• Skeleton: 
o Implementa os métodos de uma interface; 
o Faz unmarshall da requisição e invoca o método 
correspondente do objeto remoto; 
o Faz marshall do resultado (e exceções); 
o Passa a msg reply para o proxy para transmissão. 
 
Métodos fábricas 
 
• Interfaces não incluem construtores; 
• Assim, objetos remotos não podem ser criados por invocação 
remota; 
• São criados na inicialização de processos ou em métodos de 
interfaces remotas; 
• Um método fábrica é aquele que cria objetos remotos; 
• Objeto fábrica é aquele que possui métodos fábricas. 
 
Binder 
 
Serviço de um SD que mantém tabelas de mapeamento entre nomes 
de serviços e referências remotas. 
Permite aos servidores se registrarem e aos clientes procurar um 
serviço. 
• Corba: Corba Name Service; 
• Java: RMIregistry. 
 
Ativação de objetos remotos 
 
As aplicações necessitam que as informações sejam mantidas por 
longos períodos. Isso não justifica manter objetos em processos se 
eles não são necessários todo o tempo. 
Assim, os processos são disparados quando necessário. 
Um objeto remoto que pode ser invocado é chamado de ativo. 
Se ele não está ativo, mas pode ser ativado, é chamado de passivo. 
Um objeto passivo: 
• Implementação dos métodos; 
• Seu estado na forma marshalled. 
Processos que disparam servidores para manter objetos remotos são 
chamados de ativadores. 
 
 
 
6 SD Cap. 5-6 6 SD Cap. 5-6 
Armazéns de objetos persistentes 
 
Objeto persistente: pode manter seu estado e informações entre 
períodos de ativação. 
Ex.: 
• Serviço de objetos persistentes Corba; 
• Java Persistente. 
 
O processo de ativação é transparente. 
O estado dos objetos é salvo periodicamente em pontos íntegros para 
fins de tolerância a falhas. 
 
Duas abordagens para decidir se um objeto é persistente ou não: 
• Raízes persistentes: objetos acessíveis através de uma raiz 
persistente é um objeto persistente. Ex.: Java Persistente e 
PerDis; 
• Classes persistentes: objetos persistentes são instâncias dessas 
classes ou derivados delas. Ex.: Arjuna. 
 
Alguns armazéns permitem a ativação de objetos em caches dos 
clientes. Ex.: PerDis e Khazana. Isso exige um protocolo de 
consistência de caches. 
 
5.3 Remote Procedure Calling - RPC 
 
Programa distribuído: 
• Conjunto de componentes de software; 
• Executam sobre um número de computadores da rede. 
 
Modelo cliente-servidor: 
• Uma aplicação pode ser cliente de qualquer serviço da rede; 
• Um servidor pode ser cliente de outros serviços; 
• Cada serviço possui um conjunto de operações que podem ser 
invocadas pelos clientes; 
• A comunicação entre clientes e servidores é baseada no 
protocolo requisição-resposta; 
• O cliente sempre espera pela resposta para continuar, mesmo que 
não haja retorno de valor (pode haver erro!). 
 
RPC: 
• Integração entre clientes e servidores de forma conveniente; 
• Clientes se comunicam com servidores através da chamada de 
procedimentos; 
• A chamada é feita no programa local; 
• A execução ocorre num programa remoto. 
 
Serviço ao nível RPC: 
• Uma interface que é exportada para os programas de um sistema; 
• Conjunto de funções que operam sobre certos dados ou recursos; 
 
Aspectos semânticos de RPC: 
• Parâmetros de entrada e saída: 
• Parâmetros de entrada são passados para o servidor; 
• Valores enviados na requisição e copiados nas variáveis do 
servidor; 
• Parâmetros de saída são enviados para o cliente na resposta; 
• Substituem as variáveis da chamada; 
• Parâmetros podem ser I/O. 
7 SD Cap. 5-6 7 SD Cap. 5-6 
 
• Parâmetros de entrada ~ passagem por valor 
• Se passagem por referência (ptr em C): 
• Indicar se é I, O ou I/O; 
• Motivo para uma linguagem de definição de interface. 
 
• Procedimento remoto: 
• Executado em ambiente diferente de quem chama; 
• Não pode acessar dados do cliente (ex.: globais); 
• Endereços de memória do cliente não tem significado para o 
servidor; 
 
Conclusão: parâmetros não podem incluir ponteiros! 
 
Referência opaca: 
• Referência que o cliente passa para o servidor; 
• Endereço do servidor; 
• Não tem significado para o cliente. 
 
Estruturas complexas podem ser serializadas: 
• Ex.: uma árvore pode ser convertida em uma expressão. 
 
Questões de projeto 
 
Histórico: 
• 1981 - Xerox Courier RPC: padrão de desenvolvimento de 
aplicações remotas; 
• 1984 - Birrel e Nelson: 
• RPC para o ambiente de programação Cedar; 
• Datagramas sobre a Internet da Xerox; 
• Linguagem Mesa. 
 
 
Classes de RPC: 
1. o mecanismo RPC é integrado com uma linguagem específica; 
• inclui uma notação de definição de interface; 
• ex.: Cedar, Argus, Arjuna; 
• pode incluir construções específicas para RPC (ex.: 
exceções); 
2. linguagem de definição de interfaces (pré-compilador ?!). 
• ex.: SUN RPC (base do NFS); 
• Matchmaker (Jones e Rashid, 1986): pode ser usado com C, 
Pascal, LISP, MIG (Mach Interface Generator); 
• Não é ligado a um ambiente particular. 
 
 
Linguagem de definição de interfaces: 
• Especifica as características do servidor que são visíveis para o 
cliente; 
• Nomes de procedimentos, tipos dos parâmetros; 
• Tipo de acesso a um parâmetro: I, O ou I/O; 
• O acesso indica se o valor precisa ser encapsulado na requisição 
ou na resposta (marshaling); 
Compiladores de interfaces podem gerar descrições que podem ser 
usadas em diferentes linguagens, permitindo a comunicação de 
clientes e servidores de plataformas diferentes. 
 
 
8 SD Cap. 5-6 8 SD Cap. 5-6 
Tratamento de exceções: 
• Qualquer RPC pode falhar: 
• Falha no servidor; 
• Sobrecarga do servidor (atraso na resposta). 
• RPC deve devolver erros: 
• Timeouts (inerente à distribuição); 
• Erros de execução (FD inválido, leitura após EOF, divisão 
por zero, etc.). 
• Erros detectados pelos procedimentos (códigos inválidos, 
datas erradas, etc.). 
 
Obs.: na falta de um mecanismo de indicação de erros (como 
exceções em JAVA), o sistema pode usar um método bem definido 
de indicação de problemas (retorno de 0 ou –1 em UNIX). 
 
Garantia de entrega: 
Implementações possíveis do DoOperation: 
• Repetição da requisição: até receber uma resposta ou assumir 
que o servidor falhou; 
• Filtro de duplicados: usado com retransmissão, para evitar 
duplicação no servidor; 
• Retransmissão da resposta: evita a reexecução de uma 
requisição. 
 
 Garantia de Entrega Semântica RPC 
Repete Req. 
N 
S 
S 
Filtra Duplic. 
- 
N 
S 
Reexec/Retrans 
- 
Reexecuta 
Retransmite 
 
Maybe 
At-least-once 
At-most-once 
 
Tipos de semânticas RPC: 
1. Maybe: sem tolerância a falhas. Não há garantias de que o 
procedimento foi executado. Não se pode saber se o servidor 
executou a requisição ou se a resposta foi perdida. 
2. At-least-once: o cliente é informado de que um timeout ocorreu 
e retransmite a requisição. Eventualmente o servidor receberá 
uma requisição duplicada. Se ele for projetado para executar 
operações idempotentes,não há problema. 
3. At-most-once: o servidor filtra requisições duplicadas e 
retransmite as respostas. 
 
Transparência: 
• O modelo Birrel e Nelson garante que a chamada a 
procedimentos remotos é igual à chamada dos locais; 
• RPC Cedar: 
• identifica os procedimentos remotos; 
• acrescenta o código necessário para o marshalling e 
unmarshalling; 
• faz retransmissão da requisição após um timeout; 
• a duração de uma chamada é indefinida desde que o servidor 
permaneça ativo. 
 
RPC é mais vulnerável do que chamadas locais: 
• envolve redes, outros computadores e outro processos; 
• consome muito mais tempo do que chamadas locais; 
• deve tratar erros que não acontecem nas chamadas locais. 
 
 
9 SD Cap. 5-6 9 SD Cap. 5-6 
Implementação 
 
O software de suporte ao RPC tem 3 funções: 
• Processamento da interface: 
• marshalling e unmarshalling; 
• despacho das requisições. 
• Tratamento da comunicação: 
• Transmitir requisições e receber as respostas; 
• Binding: 
• Localização de um servidor para um serviço qualquer. 
 
Processamento da interface: 
 
 Requisição 
 Cliente Servidor 
Chamada Marshall Send Receive Unmarsh. Executa 
 Seleção! 
Retorno Unmarsh Receive Send Marshall Retorno 
 
 Resposta 
 
Cada procedimento de uma interface é numerado com um número 
único (0, 1, 2, 3, ...). 
 
Construindo um programa cliente: 
• Stub: 
• converte chamada local em remota; 
• faz o casamento dos parâmentros. 
 
Construindo o programa servidor: 
• entregador (despatcher); 
• conjunto de stubs servidores. 
 
Compilador de interfaces: 
• processa as definições de uma IDL. 
1. Gera os stubs do cliente; 
2. Gera os stubs do servidor; 
3. Gera as operações de marshall e unmarshall; 
4. Fornece os cabeçalhos das funções (o corpo – o que a função 
faz – deve ser fornecido pelo programador). 
Binding 
 
Mapeamento de um nome para um objeto determinado (identificador 
de comunicação). 
Ex.: no Unix, um socket com número IP e Porta. 
Ex.: Mach, Chorus e Amoeba, uma porta independente de 
localização. 
Evita a recompilação dos clientes quando o servidor muda de porta. 
Se o endereço inclui a identificação do host, o cliente precisa ser 
recompilado toda vez que o servidor mudar de host. 
Num sistema distribuído, o binding é um serviço separado que 
mantém tabelas associando nomes de serviços com portas de 
servidores. 
Ex.: o próprio Binding, DNS, etc. 
Funções: 
• Register(serviço: string, porta: port, versão: integer); 
• Withdraw(serviço: string; pota: port; versão: integer); 
• LookUp(serviço: string; versão: integer): port. 
10 SD Cap. 5-6 10 SD Cap. 5-6 
Quando um servidor inicia seus serviços, ele envia uma mensagem 
para o Binding para se registrar. 
Quando ele encerra suas atividades, ele pede para ser retirado das 
tabelas do Binding. 
 
Quando um cliente quer usar um serviço, manda uma mensagem ao 
Binding para descobrir o endereço do servidor. 
Se o servidor falha, o cliente pode requisitar ao Binding a porta de 
outro servidor do mesmo serviço. 
 
Se o sistema usa portas independentes de localização, um servidor 
pode se mover para outro host sem informar o Binding. Os clientes 
não são afetados pela mudança. 
Se o identificador de porta inclui o host, o Binding deve ser 
informado toda vez que o servidor for movido. Os clientes vão ter 
requisições ignoradas. Eles devem contatar o Binding para descobrir 
o novo endereço do serviço. 
 
Serviço único: todos os outros dependem dele: 
• Tolerante a falhas (ex.: salvando as tabelas em arquivos toda vez 
que elas são alteradas); 
 
Um sistema distribuído dependente de um único Binder não é 
escalável: 
• As tabelas podem ser particionadas (maior desempenho); 
• Também podem ser replicadas em um grupo de Binders 
(tolerância a falhas). 
 
 
 
Alguns serviços são representados por múltiplos servidores, cada um 
rodando em um host diferente: 
• Cada um deles é uma instância de um serviço; 
• Um Binder deve ser capaz de registrar as várias instâncias de um 
serviço; 
• Se o Binder não usa a instância de um serviço, o cliente deve 
informar qual delas ele quer usar (número seqüencial); 
• Numa falha, o cliente pega a próxima instância. 
• Se o Binder usar a instância, ele pode distribuir os clientes pelas 
diversas instâncias de um serviço (balanceamento de carga) 
 
Exportação: registro de um nome de interface associado com a 
porta de um servidor. 
 
Importação: pergunta ao Binder pelo nome de um serviço 
retornando um número de porta. 
 
Localização do Binder: 
• Endereço bem definido, compilado em todos os clientes; 
• Clientes e servidores precisam ser recompilados se o Binder 
for mudado; 
• O Kernel informa o endereço do Binder (ex.: variável de 
ambiente). Permite a relocação ocasional do Binder; 
• Quando clientes ou servidores iniciam, mandam mensagens de 
broadcast para localizar o Binder (ex.: no Unix, o Binder fica 
numa porta bem conhecida. Num broadcast, o Binder que 
receber informa qual é o seu host). 
 
11 SD Cap. 5-6 11 SD Cap. 5-6 
RPC Assíncrono 
 
Ex.: sistema de janelas X-11 
Utiliza uma forma assíncrona de RPC: 
 X-11 é um servidor de janelas; 
 As aplicações que querem mostrar alguma coisa na tela (texto, 
gráficos, etc.) são os clientes. 
 
Características: 
 Para gerar ou atualizar a informação de uma janela, o cliente 
envia várias requisições ao servidor, cada uma delas com uma 
pequena quantidade de informações: 
 Strings, troca de fonte, um caracter. 
 O cliente não recebe respostas para suas requisições; 
 Cliente e servidor trabalham em paralelo; 
 Algumas requisições podem exigir intensa computação - há 
ganhos em realizá-las enquanto o servidor atende requisições 
anteriores; 
 O servidor pode manipular requisições de vários clientes; 
 Ou mesmo de dispositivos; 
 O servidor tem uma performance melhor se ele não precisa 
enviar respostas para as requisições. 
 
RPC sem respostas e sem bloqueio é chamado de assíncrono. 
 
Comparação: 
• No RPC síncrono, não existe paralelismo; 
• No RPC assíncrono, o cliente faz todas as requisições de que 
necessita; só então espera pelos resultados; 
• A espera no lado do cliente se resume ao intervalo entre a última 
requisição e a recepção da primeira resposta; 
• Se não houver necessidade de resposta às requisições, o tempo 
de espera não existe. 
 
Otimização possível: 
• Armazenar as requisições no lado do servidor até que ocorra um 
timeout ou que o cliente peça uma resposta; 
• Só então as requisições são enviadas como uma comunicação só; 
• Isto reduz a latência de rede. 
Requisições paralelas para vários servidores 
 
Ex.: considere um banco com vários servidores, cada um 
responsável por registrar os lançamentos feitos em uma agência. 
• Para saber o saldo de uma conta, é preciso consultar os 
lançamentos de todas as agências; 
 
RPC síncrono: 
• O cliente faz requisições para um servidor de cada vez, 
esperando a resposta; 
• Só após chegar uma resposta, ele manda a requisição para o 
próximo. 
 
RPC assíncrono: 
• O cliente envia as requisições para todos os servidores em 
seqüência e depois espera por todas as respostas; 
• Os servidores trabalham em paralelo. 
Comparação entre RPC síncrono e assíncrono: 
12 SD Cap. 5-6 12 SD Cap. 5-6 
RPC síncrono 
argumentos 
marshall 
send 
 
 receive 
 unmarshall 
 transmissão executa 
 marshall 
 send 
 
receive 
unmarshall 
processa 
argumentos 
marshall 
send 
 
 receive 
 unmarshall 
 executa 
 marshall 
 send 
 
receive 
unmarshall 
processa 
 
Cliente Servidor 
RPC assíncrono 
 
argumentos 
marshall 
send 
argumentos 
marshall 
send 
 
 receive 
 unmarshall 
 executa 
 marshall 
 send 
 receive 
receive unmarshall 
unmarshall executa 
processa marshall 
 send 
 
receive 
unmarshall 
processa 
 
Cliente Servidor 
 
 
 
 
 
13 SD Cap. 5-6 13 SD Cap. 5-6 
RPC assíncrono no sistema Mercury 
 
Otimizações necessárias no paradigma RPC: 
• Se não há necessidadede resposta, o cliente pode fazer um 
RPC e continuar sua execução; 
• Se não há necessidade de resposta, várias requisições podem 
ser armazenadas e enviadas no mesmo send; 
• Se há necessidade de resposta, o cliente pode processar até 
que ela seja necessária para só então requisitá-la. 
 
Sistema Mercury – MIT, 1988: 
• Call-stream: combina RPC síncronos e assíncronos; 
• As diferenças nos métodos de comunicação não são visíveis para 
os servidores: 
• Eles só recebem requisições e devolvem respostas. 
• Simplifica o projeto dos servidores; 
• O cliente determina o método que vai utilizar; 
• Diferente de outros sistemas onde a interface define o método e 
o servidor precisa ser projetado de acordo; 
• Se o cliente não precisa da resposta a uma requisição, o call-
stream não a devolve para o cliente. 
Promessas 
• Liskov e Shrira, 1988; 
• Uma promessa é criada no momento de uma chamada a um 
servidor; 
• Pode assumir dois estados possíveis: 
• Bloqueado; 
• Pronto. 
• Quando criada, a promessa fica no estado bloqueado; 
• Uma promessa é associada com uma requisição específica; 
• Quando chega a resposta a essa requisição, ela é armazenada na 
promessa correspondente; 
• Neste caso, o estado da promessa passa para pronto; 
 
Funções: 
• claim(): extrai a resposta de uma promessa; 
• se ela estiver no estado bloqueado, o cliente bloqueia até que 
a promessa passe para o estado de pronto ou que ocorra uma 
exceção. 
• ready(): testa o estado de uma promessa. 
 
5.4 Eventos e notificações 
 
• Objetos que geram eventos numa plataforma distribuída 
publicam os eventos disponíveis para observação por outros 
objetos; 
• Objetos que querem receber notificações de eventos publicados 
assinam tipos de eventos em que têm interesse; 
• Objetos que representam eventos são chamados de notificações. 
 
Sistemas baseados em eventos têm 2 características principais: 
• Heterogêneos: permite que objetos não projetados para 
interoperação trabalhem em conjunto. Um sistema de eventos 
que permite publicação e assinatura pode permitir trabalho 
conjunto para objetos que não foram projetados com esse fim; 
14 SD Cap. 5-6 14 SD Cap. 5-6 
• Assíncronos: permite notificação de eventos aos assinantes sem 
necessidade de sincronismo, o que significa bloqueio dos 
envolvidos. 
 
5.4.1 Participantes em notificações de eventos 
distribuídos 
 
Arquitetura que permite independência entre autores e assinantes: 
• Banco de dados com eventos publicados e interesse dos 
assinantes; 
• Quando ocorre um evento que possui interessados, uma 
notificação é enviada. 
 
Participantes: 
• Objetos de interesse: aqueles que possuem métodos que podem 
alterar estados – isso gera eventos que podem ter interessados; 
• Evento: ocorre como resultado da execução de um método; 
• Notificação: objeto que contém informações sobre um evento: 
• Assinante: assina algum tipo de evento em outro objeto – recebe 
notificações dele; 
• Observadores: objetos que isolam autores de assinantes. Eles 
monitoram os eventos e notificam aqueles assinados; 
• Autor: objeto que declara que vai gerar notificações de certos 
tipos de eventos. Pode ser um objeto de interesse ou um 
observador. 
 
Possíveis casos de comportamento em um serviço de eventos: 
• Objetos de Interesse enviam notificações diretamente aos 
assinantes; 
• OdI enviam notificações via observadores aos assinantes; 
• OdI fora do serviço de eventos. Observadores fazem consultas ao 
OdI para descobrir quando ocorre um evento. Ele é notificado 
aos assinantes. 
 
Papéis dos observadores 
 
• Encaminhar notificações para os assinantes de um ou + objetos 
de interesse. São os objetos de interesse que informam os 
observadores sobre seus assinantes; 
• Filtros de notificações: aplicados pelos observadores para 
reduzir a quantidade de notificações. São baseados em regras 
informadas pelos assinantes. Ex.: num banco, retiradas, mas 
apenas as maiores que 10000,00; 
• Padrões de eventos: relação de eventos entre si. Ex.: num 
banco, quero ser informado sempre que houver 3 retiradas sem 
um depósito; 
• Caixas de correio para notificações: usadas para encaminhar 
notificações sem que o assinante receba na hora. Ex.: ele não 
possui uma conexão permanente, ou tornou-se passivo. As 
notificações são recuperadas mais tarde. 
 
 
 
 
 
 
 
15 SD Cap. 5-6 15 SD Cap. 5-6 
Cap. 6 – Suporte dos Sistemas 
Operacionais 
6.1 Introdução 
 
Função importantes de um SD: compartilhamento de recursos. 
• Clientes invocam operações sobre recursos em outros nós ou 
outros processos. 
 
Middleware: permite a interação entre aplicações clientes e recursos 
(gerentes). 
• O SO fica abaixo do middleware; 
• O que importa aqui é o relacionamento entre os dois; 
• Como o SO permite ao middleware o acesso aos recursos físicos, 
como ele implementa políticas de acesso, etc. 
 
Abstrações: 
• SO fornece modelos para manipular certos recursos; 
• Ex.: arquivos x blocos de disco; 
• Ex.: sockets x fluxo de redes. 
 
Num SO de rede (Unix, NT, etc.), o usuário que precisa executar um 
programa numa máquina diferente precisa se envolver: 
• Telnet, fornece senha, executa o programa. 
 
SO Distribuído: 
• O usuário não se preocupa com o nó em que seu programa 
executa; 
• Não importa onde estão os recursos; 
• O usuário vê uma única imagem do sistema; 
• A esolha de um nó para executar um programa depende da 
política de escalonamento. 
 
Caracterização de um SOD: 
• Permite a programação de um SD, permitindo a implementação 
de uma grande gama de aplicações; 
• Apresenta para as aplicações abstrações genéricas e orientadas 
aos problemas dos recursos do sistema; 
• Num SD aberto, o SOD é implementado como um conjunto de 
kernels e servidores. 
• Não há uma distinção clara entre os serviços do sistema e as 
aplicações que rodam no topo do SOD. 
 
Exemplos: Mach e Chorus. 
• Resultados de grandes períodos de pesquisa nos anos 80 e 90; 
• Alto nível de interesse técnico e comercial; 
 
Outros exemplos técnicos: 
• Amoeba, Clouds, V System; 
• Não aceitos para uso geral; 
 
Todos esses projetos empregam microkernel. 
 
SOD: 
• Infraestrutura de gerenciamento genérico de recursos e 
transparente em rede; 
16 SD Cap. 5-6 16 SD Cap. 5-6 
• Recursos de baixo nível: processadores, memória, placas de 
rede, periféricos em geral; 
• Plataforma para recursos de alto nível: planilhas, troca de 
mensagens eletrônicas, janelas; 
• Oferecidos aos clientes pelos serviços do sistema; 
 
Acesso aos recursos pelo sistema: 
• Feito de forma transparente; 
• Identificadores independentes de localização; 
• Uso das mesmas propriedades; 
• Transparência fornecida no nível mais baixo, para que não 
precise ser feita em cada serviço; 
 
Um SOD deve fornecer ferramentas para encapsular recursos: 
• De forma modular; 
• Modo protegido; 
• Amplo acesso via rede. 
 
Encapsulamento de recursos: 
• Interface padronizada – implementação escondida do usuário; 
• Concorrência – recursos compartilhados por vários usuários; 
• Proteção – segurança contra acesso ilegítimo. 
 
Os clientes acessam os recursos através da passagem de 
identificadores como argumentos: 
• Em system calls para o kernel; 
• RPC para um servidor. 
 
Invocação: acesso a um recurso encapsulado. 
Tarefas relacionadas com a invocação de recursos: 
• Resolução de nomes – localização; 
• Comunicação para acesso aos recursos; 
Escalonamento: processamento das invocações no kernel. 
 
Middleware x SOs de rede 
 
• Não há SOs distribuídos em uso corrente hoje; 
• Apenas SOs de rede (Unix, NT, MacOS, etc.); 
• Motivos: 
o Usuários se preocupam com suas aplicações de uso 
comum; 
o Não trocam seus SOs por melhor que seja um outro 
produto se não puderem executar suas aplicações; 
o Usuários preferem ter um certo controle sobre suas 
máquinas; 
o A idéia de entregar os recursos a outros usuários sem 
controle é estranha. 
 
Por outro lado, o uso de um middleware com um SO de rede é + 
versátil e aceitável: 
• O usuárioconsegue rodar seus programas favoritos; 
• Ele tem controle sobre os recursos de sua máquina; 
• Os usuários remotos têm um certo grau de transparência no 
acesso aos recursos da rede; 
• É possível acessar recursos compartilhados com um certo grau 
de concorrência. 
 
17 SD Cap. 5-6 17 SD Cap. 5-6 
6.2 Camada de sistema operacional 
 
 
Aplicações, serviços 
 
 
Middleware 
 
OS1 
Processos, threads, 
comunicação, etc. 
 
OS2 
Processos, threads, 
comunicação, etc. 
Hardware do 
computador e rede 
 
Hardware do 
computador e rede 
Nó 1 
 
Nó 2 
 
As interfaces apresentadas por kernels e servidores devem apresentar 
pelo menos o seguinte: 
• Encapsulamento: conjunto mínimo de operações fornecidas aos 
clientes. Detalhes de implementação escondidos; 
• Proteção: evita acessos indevidos; 
• Concorrência: clientes devem acessar os recursos de forma 
concorrente. Isso deve ser transparente para eles. 
Kernel 
 
Kernels e proteção: 
• O Kernel executa com privilégio de acesso total; 
• Ex.: pode controlar a unidade de MM; 
• Pode conceder privilégio de acesso a recursos físicos; 
• Determina o espaço de endereçamento: 
• Permite que os processos se protejam uns dos outros; 
• Evita que um processo invada áreas indevidas. 
• Modo supervisor e usuário: 
• Processos usuários podem rodar em modo supervisor quando 
tem acesso direto a um dispositivo; 
• System call trap: mecanismo de invocação de recursos 
gerenciados pelo kernel; 
 
Kernel monolítico e microkernel – um SOD aberto deve permitir: 
• Executar apenas o suficiente para tornar o ambiente operacional 
(módulos supérfluos gastam recursos); 
• Alterações no software ou sistema que implementa um serviço, 
independentemente de outros elementos; 
• Alternativas do mesmo serviço para atender usuários ou 
aplicações diferentes; 
• Introdução de novos serviços sem prejudicar os existentes. 
 
Um certo grau de abertura é obtido com a utilização de kernels 
tradicionais como base. 
Ex.: o DCE da OSF usa Unix, VMS, OS/2, etc. 
• Permitem a execução de processos servidores; 
• Suportam protocolos (ex.: RPC); 
• Possuem binding e serviços de nomes; 
• Serviços de tempo (sincronização); 
• Segurança; 
• Threads. 
18 SD Cap. 5-6 18 SD Cap. 5-6 
Unix: 
• Monolítico; 
• Sugere um sistema massivo; 
• Executa todas as operações básicas do sistema; 
• 1 MB de código e dados; 
• Não diferenciável: codificado de forma não modular; 
• Intratável: a alteração de um módulo para adequação a novos 
requisitos é muito difícil. 
 
 
 Carregado dinamicamente 
 
 
 
 
 
 
Kernel monolítico MicroKernel 
 
 
Principais funções de um microkernel: 
• Processos; 
• Memória; 
• IPC; 
• Todos os outros serviços carregados dinamicamente em 
servidores específicos; 
• Um serviço extra só é carregado na máquina que precisa dele; 
• Acesso via invocação (RPC). 
 
O microkernel na hierarquia de um sistema: 
 
 
 
 
 
 
 
 
 
 
Comparação: 
• Abertura; 
• Modularidade; 
• Um kernel pequeno tem mais chances de ter menos bugs; 
• Mais fácil de manter; 
 
• Kernel monolítico é mais difícil de ser modular; 
• Impossível extrair um módulo para execução remota; 
• Um bug num módulo pode se espalhar para os demais; 
• Alterar um módulo implica em recompilar o kernel e reiniciá-lo; 
• Vantagem: eficiência para realizar as tarefas. 
Arquitetura de um microkernel 
 
Em princípio, não há uma definição clara de quais módulos um 
microkernel deve ter. 
Todos os produtos dessa categoria incluem: 
 Gerência de processos; 
 Gerência de memória; 
Sn 
S1 S2 S3 S3S2S1
Microkernel
Hardware
Serviços abertos processos/objetos das aplicações 
Suporte de 
linguagem 
Suporte de 
linguagem 
Emulação 
de OS 
19 SD Cap. 5-6 19 SD Cap. 5-6 
 Passagem de mensagens local. 
 Tamanho: 10 KB até várias centenas de KB de código e dados 
estáticos. 
 
Microkernels são projetados para serem portáveis: 
 A maior parte de seu código é escrito em linguagem de alto nível 
(C, C++, etc.); 
 Recursos físicos são agrupados em camadas; 
 Componentes dependentes de máquina são reduzidos: 
 Manipulação do processador, unidade de gerência de 
memória, registradores da unidade de ponto flutuante; 
 Tratamento de interrupções; 
 Traps; 
 Exceções. 
 
A arquitetura de um microkernel geral pode ser visto na figura: 
 
 Aplicações 
 
 
 
 
 
 
 
 
 
 
 
 Hardware 
 Gerente de processos: criação, interface, etc. 
 Gerente de Threads: criação, sincronização, escalonamento. 
Processadores disponíveis. Política de escalonamento a critério 
do usuário. 
 Gerente de comunicação: IPC. 
 Gerente de memória: memória física, MMU, caches. 
 Supervisor: tratamento de interrupções, system calls, exceções. 
6.4 Processos e threads 
 
Unix: 1 processo, 1 atividade de processamento (1980). 
Processo: recurso caro para criar e manter. 
O compartilhamento entre atividades relacionadas é caro e 
complexo. 
 
Solução: generalização do conceito de processo. 
 Associar mais de uma atividade ao mesmo processo. 
 Processo: ambiente de execução + 1 ou mais threads. 
 Thread: abstração de atividade do sistema operacional. 
 "Thread of execution". 
 
 Ambiente de execução: unidade de gerenciamento de recursos. 
 Coleção de recursos gerenciados pelo kernel local, aos quais suas 
threads têm acesso; 
 
Ambiente de execução: 
 Espaço de endereçamento; 
 Sincronização de threads e IPC, como semáforos; interfaces de 
comunicação (portas); 
 Recursos de alto nível (arquivos, janelas, etc.). 
Gerente de Processos 
 
 
 
 
 
 
 
 
Supervisor
 
 
 
 
Gerente de 
Threads 
 
 
 
 
Gerente de 
Memória 
Gerente 
de 
Comunicações 
20 SD Cap. 5-6 20 SD Cap. 5-6 
Obs.: num microkernel, recursos de alto nível como arquivos e 
janelas não fazem parte dos recursos de um ambiente de execução. 
São acessados via servidores. 
 
 Ambientes de execução são caros e difíceis de criar; 
 Várias threads podem compartilhar o mesmo ambiente; 
 Threads podem ser criadas e destruídas dinamicamente; 
 Objetivo: maximizar o grau de concorrência entre operações 
relacionadas. 
 Threads: lightweight process. 
6.4.1 Espaços de endereçamento 
 
• Os espaços não são contíguos. 
• Gaps permitem o crescimento das regiões. 
 
• Componente mais caro de um ambiente de execução; 
• Grande (232 é um valor típico); 
• Consiste de uma ou mais regiões; 
• Região: área contígua de memória virtual acessível pelas threads 
do processo; Regiões não se sobrepõem; 
 
Propriedades das regiões: 
• Extensão: endereço mais baixo e tamanho; 
• Permissões para as threads: read/write/execute; 
• Direção de crescimento: para cima ou para baixo; 
 
Analogia para processos e threads: 
• Um ambiente de execução consiste de um jarro com água e 
comida; 
• A 1ª thread desse processo é uma mosca dentro do jarro; 
• A mosca pode gerar filhos (outras threads) ou matá-los; 
• As moscas podem consumir a água e/ou a comida; 
 
 2N 
 
 
 
 
 
 
 
 
 
Memória Gaps 
Virtual 
 
(ex.: 232) 
 
 
 
 
 
 
 
 
 0 
 
♦♦♦♦♦♦♦♦♦♦♦♦♦♦♦♦♦♦♦ 
 
 
Regiões 
Auxiliares 
 
♦♦♦♦♦♦♦♦♦♦♦♦♦♦♦♦♦♦♦ 
 
 
♦♦♦♦♦♦♦♦Stack♦♦♦♦♦♦♦♦ 
 
 
 
 
 
♦♦♦♦♦♦♦♦Heap♦♦♦♦♦♦♦♦ 
 
 
 
 
♦♦♦♦♦♦♦♦♦Text♦♦♦♦♦♦♦♦
21 SD Cap. 5-6 21 SD Cap. 5-6 
• Uma mosca não pode sair de seu jarro para entrar em outros 
jarros; 
• As moscas podem colidir, quando resultados imprevisíveis 
poderão ocorrer; 
• As moscas podem consumir toda a água e comida – o ambiente 
passa a ser inviável. 
 
O sistema com um número indefinido de regiões permite o 
mapeamento de arquivos no espaço de endereçamento: 
• Um arquivo mapeado é acessado como um array de bytes; 
• O sistema VM garante que as atualizações se reflitam no sistema 
de arquivos. 
6.4.2 Criação de um novo processo 
 
Unix: 
• Um processo que chama o comando fork() cria um novo 
processo copiando o seu espaço de endereçamento; 
• A diferença é o valor retornado pelo fork(); 
• O comando exec() transforma o programa que chama num 
processo do arquivo em disco passado como parâmetro.Num SD, há duas novas considerações: 
• Múltiplos computadores; 
• A infraestrutura de suporte reside em serviços separados. 
 
Aspectos de criação de processos em um SD: 
• Escolha do host alvo (onde o novo processo vai residir); 
• Criação de um ambiente de execução; 
• Criação de uma thread, com um ponteiro de pilha default e um 
contador de instruções. 
 
Escolha de um host alvo 
 
Depende do sistema: 
• V System: executa um processo num host determinado ou no 
mais ocioso; 
• Amoeba: escolhe um dos processadores do pool onde o processo 
vai residir. É transparente. 
 
Depende da necessidade. Se é necessário trabalhar com paralelismo 
explícito, pode ser necessário indicar hosts específicos. 
 
Tipos de políticas: 
• Política de transferência: diz se um novo processo é local ou é 
executado num host remoto. Depende da carga; 
• Política de localização: determina o host remoto que recebe um 
novo processo; 
o Depende da carga, da arquitetura e de possíveis recursos 
especializados que o host tem. 
 
As políticas podem ser estáticas ou adaptativas: 
• Estáticas não consideram o estado atual do sistema; 
o Podem ser deterministas (a transferência sempre ocorre 
de A para B); 
o Ou probabilísticas (a transferência ocorre de A para um 
entre B-E – escolha aleatória). 
• Adaptativas: usam heurísticas sobre fatores momentâneos. 
 
22 SD Cap. 5-6 22 SD Cap. 5-6 
Sistemas de carga compartilhada: 
• Centralizados: um gerente de carga para o sistema; 
• Hierárquicos: vários gerentes, organizados em árvore; 
• Decentralizados: todos são gerentes. 
 
Tipos de algoritmos de carga compartilhada: 
• Iniciados pelo transmissor: disparado quando a carga local 
atinge um limite máximo; 
• Iniciados pelo receptor: quando a carga local cai abaixo de um 
certo valor, o nó avisa os demais que passou a ser um receptor de 
carga. 
 
Sistemas migratórios: a carga pode ser distribuída a qualquer 
momento: 
• Recurso pouco usado; 
• O custo para transferir um processo é muito alto; 
• Extrair o estado de um processo do kernel é muito difícil. 
 
Criação de um novo ambiente de execução 
 
Opções: 
• O sistema inicia um espaço de endereçamento genérico, baseado 
em certos parâmetros que ele possui: tamanho da área de código, 
stack, etc. 
• Geração a partir de um já existente: fork() 
• Pai e filho compartilham a área de código! 
• Isto é feito pelo mapeamento da região de texto do pai dentro 
do espaço de endereçamento do filho. 
• Stack e heap são copiados do pai para o filho. 
• Mach e Chorus: usam copy-on-write: 
• Regiões herdadas do pai são copiadas apenas logicamente; 
• A cópia física só ocorre quando um dos processos tenta 
escrever sobre a região: 
• O compartilhamento é desfeito; 
• Ocorre a cópia física; 
• Esta cópia pode acontecer em disco, caso ocorra um page 
fault. 
 
Obs.: herança é um problema caso haja uma ou mais portas em uso 
pelo processo pai. Dois processos não podem compartilhar fluxos de 
mensagens. 
6.4.3 Threads 
 
Considere um servidor com uma ou mais threads. 
Assumimos que uma requisição qualquer utiliza 2 msegs de 
tratamento e 8 msegs de I/O (sem o uso de cache). O computador 
possui apenas um processador. 
Máximo throughput dependendo do número de threads: 
• 1: 2 + 8 = 10 msegs. 100 requisições por segundo. 
• 2: uma thread pode processar enquanto a outra está esperando. 
 
As threads de um processo não podem fazer I/O em paralelo. Assim, 
todos os I/Os devem ser feitos seqüencialmente. 
Se todas as requisições de I/O forem serializadas, temos 
1000/8 = 125 requisições por segundo. 
 
23 SD Cap. 5-6 23 SD Cap. 5-6 
Considere agora um cache de blocos de disco. O servidor mantém 
blocos em buffers em seu espaço de endereçamento. Se há uma 
requisição, ele 1º verifica se o bloco está no cache. Se estiver, a 
requisição é atendida com I/O zero. 
 
Considerando uma taxa de acerto de 75%, 
Tempo médio por requisição = 0,25 * 8 + 0,75 * 0 = 2 msegs. 
Máximo throughput = 500 requisições por segundo. 
 
Entretanto, há um acréscimo de tempo pela pesquisa no cache. 
Vamos supor que o tempo médio por requisição real seja de 2,5 
msegs. 
Máximo throughput = 400 requisições por segundo. 
 
Arquiteturas para servidores multi-thread 
 
Pool de trabalhadores: 
• O servidor mantém um pool de trabalhadores para processar as 
requisições; 
• Em geral, uma thread de I/O recebe as msgs através de várias 
conexões; 
• As requisições são colocadas em filas para tratamento. 
 
Threads-por-requisição: 
• A thread de I/O cria uma thread para cada requisição que chega; 
• Ela se destrói quando a tarefa está feita; 
• Maximiza o I/O; 
• Custo de criação e destruição de threads. 
 
 
Threads-por-conexão: 
• O servidor coloca uma thread para cada conexão de cliente; 
• Em uma conexão, cada cliente pode fazer várias requisições. 
 
Threads-por-objeto: 
• Uma thread associada a cada objeto remoto; 
• Cada objeto possui sua fila. 
 
Threads nos clientes 
 
Nos clientes, o uso de threads é interessante para evitar bloqueios 
indesejáveis em certas operações: 
• Em requisições a um servidor; 
• Em RMI (ou RPC), quando se faz invocação a um objeto 
remoto. 
 
Formas organização de threads nos clientes: 
• Por requisição: para cada requisição feita no cliente é disparada 
uma thread que gerencia o processo; 
• Por conexão: cada conexão estabelecida com um servidor 
remoto recebe uma thread – toda comunicação nessa conexão é 
feita por meio dela; 
• Por objeto: para cada objeto remoto usado pelo cliente é 
disparada uma thread – cada uma faz as invocações remotas para 
o seu objeto. 
 
Threads x múltiplos processos 
 
A mesma sobreposição pode ser alcançada por múltiplos processos. 
Por que um sistema multithread é preferível? 
24 SD Cap. 5-6 24 SD Cap. 5-6 
Ambiente de execução (processo): 
• Espaço de endereçamento; 
• Portas, interfaces de comunicação, etc. 
• Semáforos, objetos de sincronização, etc. 
• Lista de threads. 
 
Thread: 
• Registradores salvos; 
• Estado (ex.: bloqueado) e prioridade; 
• Informação sobre tratamento de interrupções. 
 
Elementos comuns entre processos e threads: 
• Páginas residentes em memória; 
• Entradas de caches. 
 
Sumário: 
• Criar uma nova thread para um processo já existente é mais 
barato do que criar um novo processo; 
• Chavear para outra thread de um processo é mais barato do que 
para threads de processos diferentes; 
• O compartilhamento dos recursos de um processo por suas 
threads é mais simples do que por processos separados; 
• O problema é que as threads não têm proteção uma das outras. 
 
Custo de criação de uma thread: 
 Alocação da região da pilha; 
 Valores iniciais para os registradores; 
 Estado inicial: SUSPENDED ou RUNNABLE; 
 Prioridade; 
 Acréscimo de identificador no registro de threads. 
Comparação de tempos: 
 Sistema Unix; 
 Arquitetura CVAX; 
 Kernel Topaz; 
 Anderson et al., 1991; 
 Teste: processo ou thread criados para fazer uma chamada nula; 
 Processo: 11 msegs; 
 Thread: 1 mseg. 
 
Memória: 
 Um processo recebe page faults logo que inicia sua execução; 
 Uma thread também! 
 Entretanto, threads podem se beneficiar dos acessos feitos sobre 
suas áreas por outras threads; 
 Pode aproveitar áreas colocadas nos caches por outras threads. 
 
Programação de Threads 
 
A programação de threads é Programação Concorrente! 
Conceitos desta seção: race conditions, seção crítica, variáveis de 
condição e semáforos. 
 
Ex.: 
 Modula-3, Java: suporte direto à threads; 
 C: extensão por biblioteca; 
 P Threads: padrão de threads para o Posix desenvolvido pelo 
IEEE; 
 GNU Threads: padrão da Free Software Foundation para o 
SunOS. 
 
25 SD Cap. 5-6 25 SD Cap. 5-6 
Chamadas Java para manipulação de Threads: 
• Thread(ThreadGroup grupo, Runnable alvo, String nome) – cria 
uma nova thread no estado SUSPENDED, que pertence a grupo 
e é identificada como nome; passa a executar pela chamada do 
método run() de alvo. 
• setPriority(int newPriority), getPriority() – muda ou retorna a 
prioridadeda thread. 
• Run() – executa o método run() de seu objeto alvo, se houver; ou 
seu próprio método run() (Thread implementa Runnable). 
• start() – muda o estado da thread de SUSPENDED para 
RUNNABLE. 
• sleep(int millisecs) – a thread passa para o estado SUSPENDED 
pelo tempo especificado. 
• yield() – passa para o estado READY e chama o escalonador. 
• destroy() – destrói a thread. 
 
Obs.: 
• Grupos são isolados uns dos outros, no sentido de que não 
podem ser gerenciados entre si; 
• Threads de um grupo não podem criar threads de outro; 
• Grupos podem ter prioridades limites estabelecidas pelo 
processo. 
 
Chamadas da biblioteca C Threads: 
 threadId = cthread_fork(func, arg) - permite criar uma thread a 
partir de outra, que executa a função func passando um só 
argumento arg; 
 cthread_exit(result) - termina a thread atual; 
 cthread_join(threadId) - a thread que criou threadId espera até o 
seu término; 
 cthread_set_data(threadId, data) - associa dados globais 
exclusivamente com uma thread; 
 cthread_data(threadId) - libera os dados associados a uma 
thread; 
 cthread_yield() - permite que outra thread rode. 
 
Problemas com Threads: 
 <stdio.h> em C; 
 1 buffer para cada stream de I/O (ex.: vídeo) 
 o problema ocorre quando mais de uma thread tenta mandar 
caracteres para um terminal; 
 a ordem depende do escalonador; 
 a biblioteca mantém um ponteiro para a posição no buffer onde o 
próximo caracter deve ser colocado: 
 pode levar a race conditions. 
 
Chamadas de sincronização da biblioteca C Threads: 
 mutex_lock(mutexId) 
 mutex_unlock(mutexId) 
 condition_wait(conditionId, mutexId) 
 condition_signal(conditionId) 
 
 
Escalonamento de Threads 
 Preemptivo: uma thread pode ser suspensa pelo escalonador para 
que outra execute; 
 Não preemptivo (corrotina): uma thread executa até fazer uma 
chamada que cause sua suspensão. 
 
Corrotinas: 
26 SD Cap. 5-6 26 SD Cap. 5-6 
 Qualquer seção que não apresenta chamadas é uma seção crítica; 
 Só servem para máquinas com 1 processador; 
 Não servem para Real Time; 
 Aplicações processor bound devem dar chances às outras (yield). 
 
Implementação de Threads 
 Alguns kernels permitem processos com apenas uma thread; 
 Porém, há bibliotecas que permitem implementar processos 
multithreads. 
 
Ex.: SunOS 4.1 Lightweight Processes (pacote) 
 O kernel não reconhece as threads; 
 Não há escalonamento de threads independentemente; 
 Se alguém (o processo ou uma thread) faz uma sys call 
bloqueante, todos bloqueiam; 
 As threads de um processo nessas condições não podem executar 
num sistema multiprocessador; 
 A troca de contexto de threads dentro de um processo não 
precisa ser feita via sys call; 
 O escalonamento pode ser específico da aplicação; 
 
Psyche (SO multiprocessador) - processador virtual (PV): 
 Um PV é um recurso pertencente a um processo; 
 Implementado no kernel; 
 Associado com processadores reais; 
 O processo controla esses recursos diretamente; 
 Cada um executa uma função; 
 O kernel informa o processo dos eventos; 
 O processo pode trocar uma thread bloqueada em um PV; 
 Ou pode trocar o PV de um processador real. 
6.4 Nomes e proteção 
 
Um serviço em geral gerencia vários recursos: 
 Cada um deles pode ser acessado independentemente pelos 
clientes; 
 Para esta finalidade, o serviço fornece identificadores para cada 
um dos seus recursos; 
 Serviços precisam ser reconfiguráveis - flexíveis: 
 Para um grupo de servidores gerenciar um recurso 
individual; 
 Para se localizar os servidores. 
Clientes acessam recursos através de requisições a um serviço, 
passando o identificador correto. 
 Requisições são passadas a identificadores de comunicação, que 
podem ser obtidos de um serviço de binding; 
 Mach e Amoeba: portas; 
 Chorus: grupos de portas. 
 
Identificação de um recurso – deve-se fornecer: 
 Porta (grupo) de acesso ao servidor que gerencia o recurso; 
 Identificador específico. 
 
• Identificadores independentes de localização fornecem 
transparência de rede; 
• O formato dos identificadores é escolhido por quem implementa 
o serviço; 
• É boa prática usar o mesmo formato para a mesma família de 
serviços; 
• Facilita a administração e marshalling; 
27 SD Cap. 5-6 27 SD Cap. 5-6 
• Identificadores devem ser únicos num SD inteiro ou, ao menos, 
dentro de um serviço; 
• Amoeba: identificadores únicos em todo o SD; 
• Permite usar um identificador sem saber de que serviço ele é! 
Reconfigurabilidade 
 
Capacidade de um SD de se adaptar à evolução ou mudanças em 
suas condições, tais como carga de rede ou falhas: 
• Relocação de servidores: ocorre pela criação de novas instâncias 
de servidores ou por migração; 
• Mobilidade de recursos: recursos migram de um servidor para 
outro no mesmo serviço. 
• É preciso manter as transparências de localização e de migração; 
• Problema: como reconfigurar o serviço on-line? 
Proteção de recursos 
 
Objetivo: garantir que os processos só possam acessar os recursos 
para os quais tenham permissão. 
 
 
Problemas: 
• As redes devem ter abertura; 
• Os computadores de um SD podem sofrer ataques que alterem 
seu software; 
• A proteção deve ser específica por serviço; 
• Os servidores podem receber qualquer requisição de qualquer 
computador/processo da rede; 
Domínios de proteção 
 
• Já visto em SO I; 
• Conjunto de pares (recurso, direitos), relacionando todos os 
recursos que podem ser acessados pelos processos que rodam 
nesse domínio; 
 
Ex.: Unix – domínio determinado pelo grupo e usuário. Os direitos 
são determinados pelas operações RWX. 
 
Implementações: 
• Capabilities e Listas de controle de acesso. 
6.5 Comunicação e invocação 
 
Formas de comunicação: 
• Produtor-consumidor; 
• Cliente-servidor; 
• Comunicação de grupo. 
 
 
Formas de qualidade de serviço: 
• Garantia de entrega; 
• Banda de transmissão; 
• Latência; 
• Segurança. 
 
Questões relacionadas aos serviços de comunicação: 
• Primitivas disponíveis; 
28 SD Cap. 5-6 28 SD Cap. 5-6 
• Garantias de QoS; 
• Protocolos; 
• Abertura da implementação; 
• Procedimentos para aumentar a eficiência. 
Primitivas de comunicação 
 
Formas de passagem de mensagens: 
• Send-receive; 
• DoOperation-GetRequest-SendReply. 
 
A implementação depende dos recursos disponíveis: 
• As primitivas podem ser confiáveis; 
• Se não forem, isso pode ser alcançado em níveis mais altos; 
• Uma das formas pode ser implementada usando a outra; 
• Isso pode ser feito em baixo nível (kernel) ou em alto nível (até 
na aplicação). 
Compartilhamento de memória 
• Comunicação local deve ser feita pela transferência do conteúdo 
de áreas de memória entre os processos; 
• Feito pelo kernel através de operações especiais (Copy-on-
write); 
• Transfere dados de páginas de um espaço de endereçamento para 
páginas de outro; 
• Regiões compartilhadas podem ser usadas para facilitar (dar 
mais velocidade) a comunicação processo-kernel e/ou processo-
processo; 
• Problemas: 
• Sincronismo; 
• Justifica se for bastante usado, já que o custo para estabelecer 
é alto. 
 
Qualidade de Serviço 
O que é possível fazer com primitivas não confiáveis? 
 É possível construir uma versão confiável de um Send; 
 Até um RPC com semântica at-least-once ou mesmo at-most-
once; 
 Comunicação orientada a streams, com um sistema apropriado 
de buffers; 
 Multicast de alto nível; 
 Segurança para a comunicação, passando por um serviço de 
criptografia; 
 
Principal dificuldade é latência satisfatória: 
 Há serviços que precisam de mais latência do que outros; 
 Multimídia impõem restrições de tempo real; 
 O SO deve atender as solicitações de um mínimo de qualidade 
dos usuários ou recusar o serviço; 
 
 
Protocolos e abertura 
 
 Alguns sistemas incorporam seus próprios protocolos: 
 Ex.: Amoeba - Amoeba RPC; 
 V system - VMTP; 
 Sprite - Sprite RPC. 
 Problema: esses protocolos não são usados em ambientes de uso 
geral; 
29 SD Cap. 5-6 29 SD Cap. 5-6 
 TCP, UDP e IP nãosuportam RPC diretamente; 
 Mach e Chorus têm outra estratégia: 
 Suportam apenas passagem de mensagens local; 
 Usam servidores no topo do kernel para tratar os protocolos 
de rede; 
 Sistema aberto, já que qualquer um pode implementar seu 
próprio servidor. 
 
Desempenho de Invocação 
 
Mecanismos de invocação: 
• Chamar um procedimento local; 
• System call; 
• Enviar uma mensagem; 
• RPC; 
• Chamar um método de um objeto, etc. 
 
Em todos os casos, código é executado fora dos limites de quem 
chama. 
É preciso passar argumentos e retornar dados para quem chama. 
 
 
 
 
 
 
 
 
 
 
Tipos de operações entre espaços de endereçamento: 
 
Thread 
 
User kernel 
 
Thread 1 Thread 2 
 
User 1 Kernel User 2 
 
 
 
Thread 1 Thread 2 
 Rede 
User 1 Kernel 1 Kernel 2 User 2 
 
 
Tipos de operação: 
• Síncronas: chamada local e RPC; 
• Assíncronas: operação sem retorno de valores. 
 
Desempenho de RPC 
 
RPC nulo: RPC sem parâmetros, que executa um procedimento nulo 
e não retorna valores. 
• Melhor tempo reportado para um RPC nulo entre 2 processos 
usuários através de uma LAN: 1 milisegundo! 
• Uma chamada local de procedimento é executada numa fração 
pequena deste tempo. 
trap
Instruções privilegiadas
System Call
RPC (no mesmo 
computador 
RPC (entre 
computadores) 
30 SD Cap. 5-6 30 SD Cap. 5-6 
• Um RPC nulo transfere cerca de 100 bytes, somando dados de 
cabeçalhos de pacotes de rede. 
• A 100 Mbits/seg., o tempo total de rede para transferir essa 
quantidade é cerca de 0,1 milisegundos. 
• A maioria do tempo é composta de atrasos impostos pelo SO e 
pelo código do RPC no nível do usuário. 
 
Estudo sobre a média de RPCs chamados (Bershad, 1990 – 1,5 
milhão de chamadas): 
• A chamada mais freqüente é de menos de 50 bytes do usuário; 
• A maioria das chamadas transfere menos que 200 bytes; 
• RPC que transfere blocos de disco tende a ter 1-8 kb; 
• O uso de caches tende a diminuir a freqüência dessas chamadas. 
 
A maioria das chamadas RPC cabe num pacote de rede (em torno de 
1 KB). 
Um RPC nulo representa o overhead fixo que uma chamada 
apresenta. 
 
Figura 6.14: 
• O atraso de um RCP cresce proporcionalmente ao tamanho do 
pacote; 
• Há um salto toda vez que é preciso acrescentar mais um pacote 
na chamada. 
 
Throughput: 
• O atraso não é o único elemento de interesse no RPC; 
• Throughput: taxa na qual os dados podem ser transferidos entre 
computadores; 
• Na fig. 6.14, o throughput é pequeno para pequenas quantidades 
de dados; 
• À medida que cresce a quantidade de dados, cresce o throughput, 
já que o overhead fixo torna-se menos significativo; 
• Hutchinson, 1989 – máximo throughput = 750 KB/seg. (Ethernet 
10 Mbits/seg!); 
• O throughput para quantidades maiores de dados deve aumentar 
bastante com redes de 100 Mbits/seg (ou mais)! 
• Mesmo assim, para quantidades pequenas o overhead fixo deve 
predominar; 
 
Quais são esses overheads e o que fazer para minimizá-los? 
 
Passos de um RPC: 
• Stub do cliente: 
• Marshalling dos argumentos; 
• Envio da requisição; 
• Recepção da resposta; 
• Unmarshalling da resposta. 
• Servidor: 
• Dispatcher recebe a requisição; 
• Chama o stub apropriado do servidor. 
 
• Stub do servidor: 
• Unmarshall dos argumentos; 
• Chamada do procedimento correto; 
• Marshalling dos argumentos; 
• Envio da resposta. 
 
31 SD Cap. 5-6 31 SD Cap. 5-6 
Principais componentes do atraso de um RPC: 
• Marshalling: significa copiar e converter dados; 
• Cresce à medida que a quantidade de dados aumenta. 
• Cópia de dados: 
• Cópia de memória para memória fica em torno de 10 
MB/seg. nos processadores mais rápidos; 
• Mesma taxa de transferência de uma rede 100 Mbits/seg; 
• Uma mensagem pode ser copiada diversas vezes num RPC: 
• Entre usuário e kernel; 
• Entre cliente e servidor; 
• Nos buffers do kernel; 
• Entre as camadas dos protocolos; 
• Entre as interfaces de rede e os buffers do kernel. 
 
Obs.: no sentido interface-memória (na chegada), a transferência é 
feita por DMA. 
 
• Inicialização de pacotes (headers, checksums, etc.): custo 
proporcional à quantidade de dados; 
• Escalonamento de threads e troca de contexto: 
• RPC invoca sistema de comunicação do kernel; 
• Aplicação usa threads para fazer um RPC; 
• Se há um processo gerente de rede, um Send implica em 
troca de contexto. 
6.6 Memória virtual 
 
Objetivo: executar grandes problemas e combinações de programas 
cuja soma de código e dados é maior que a memória principal: 
 Parte da memória é usada como cache do sistema de 
armazenamento. 
 
Por manter apenas as seções de código e dados atualmente em uso 
pelos processos, é possível: 
 Executar programas maiores que a memória principal; 
 Aumentar o nível de multiprogramação ao aumentar o número 
de processos na memória principal; 
 Liberar os programadores das limitações da memória física. 
 
Idéia generalizada para abranger o acesso a arquivos mapeados em 
áreas de memória: 
 Um processo lê ou grave dados no arquivo lendo ou gravando 
num array em memória; 
 Um arquivo aberto para uma linguagem de alto nível aparece 
como um array; 
 O kernel é responsável por trazer mais dados à medida que os 
dados do array são lidos; 
 O kernel transfere os dados para disco à medida que eles são 
alterados 
Ex.: MULTICS, SunOS. 
Demand paging: uma página só é carregada por demanda (isto é, 
quando alguém precisa, ela é carregada para a memória principal). 
 
Gerenciadores externos 
 
Em um SD, o computador que recebe um page fault não precisa ser 
o mesmo que gerencia os dados: 
 Ex.: o 1o pode ser diskless; 
 O gerente é um servidor de arquivos remoto; 
32 SD Cap. 5-6 32 SD Cap. 5-6 
 
 
 
 
 
 
 
 
 
 
 
 O uso de gerenciadores externos permite implementar esquemas 
customizados de paginação; 
 Uma abordagem para implementar memória compartilhada 
distribuída; 
 O kernel continua responsável por: 
 tratar page faults; 
 gerência da memória principal; 
 política de alocação; 
 política de substituição. 
 Função do gerenciador externo: 
 Receber e tratar dados de páginas purgadas pelo kernel; 
 Fornecer páginas ao kernel conforme ele peça; 
 Impor restrições aos diversos kernels que acessam uma área 
(todos podem tentar manter caches de áreas modificáveis). 
 
Espaço de 
endereça- 
mento 
Kernel Kernel
rede 
Page fault 
msgs 
Gerente 
externo

Continue navegando