SISTEMAS DISTRIBUÍDOS Prof. Ricardo Rodrigues Barcelar http://www.ricardobarcelar.com.br - Aula 5 – PROCESSOS 1. INTRODUÇÃO Em sistemas distribuídos é importante examinar os diferentes tipos de processos e como eles desempenham seu papel. O conceito de um processo é originário do campo de sistemas operacionais no qual ele é definido como um programa em execução. Da perspectiva de Sistema Operacional, o gerenciamento e o escalonamento de processos são talvez as questões mais importantes. 2. PROCESSOS Sistemas Operacionais modernos criam vários processadores virtuais, cada um para executar um programa. Para monitorar os processadores virtuais o sistema operacional tem uma tabela de processos que contém entradas para armazenar valores de registradores de CPU, mapas de memória, arquivos abertos, etc. Como visto os processos podem ser considerados programas em execução, na qual o Sistema Operacional é o responsável por assegurar que processos independentes não afetem (modos intencional, malicioso ou acidental) a correção do comportamento dos outros processos sendo executados. Nesta ótica deve também existir transparência no compartilhamento da mesma CPU e outros recursos de hardware. A transparência implica em custos como: - Criação de espaço de endereços completamente independente - Chavear a CPU entre dois processos - Salvar o contexto da CPU - Troca de informações entre disco e memória principal Neste sentido, em sistemas tradicionais, cada processo deve possuir o seu próprio espaço de endereçamento e um único fluxo de execução. No entanto, em alguns casos é desejável haver diversos fluxos de execução compartilhando um único espaço de endereçamento, ou seja, mesma região de memória. Em havendo um único fluxo de execução ocorre certa perda de desempenho. Como exemplo, um servidor de arquivos deve esperar por requisições feitas ao disco, visto que o fluxo de execução que fez a requisição é bloqueado aguardando a resposta. Com vários fluxos de execução existe melhor vazão (throughput) e ganho de desempenho. Seguindo o mesmo exemplo, se um servidor de arquivos é implementado usando diferentes fluxos de execução, outras requisições de clientes podem ser processadas, enquanto o primeiro fluxo aguarda a resposta do disco. Este é o princípio das threads. 1 SISTEMAS DISTRIBUÍDOS Prof. Ricardo Rodrigues Barcelar http://www.ricardobarcelar.com.br 3. THREADS Embora processos formem um bloco de construção em sistemas distribuídos, a prática indica que a granularidade de processos proporcionada pelos sistemas operacionais sobre os quais os sistemas distribuídos são construídos não é suficiente. Em vez disso, observa-se que ter granularidade sob a forma de múltiplos threads de controle por processo facilita muito a construção de aplicações distribuídas e a obtenção de melhor desempenho. Figura 1 - Processo vs Thread Cada um dos fluxos de execução de um processo é chamado de thread, ou seja, as threads podem ser vistas como mini-processos, onde cada thread executa sua própria porção de código. Cada thread compartilha a CPU do mesmo modo que diferentes processos compartilham (timesharing). 3.1. Threads em sistemas não-distribuídos As threads que fazem parte de um mesmo processo não são independentes como no caso de diferentes processos. Todas as threads em um mesmo processo possuem a mesma região de memória e compartilhando as mesmas variáveis globais. Sendo assim, uma determinada thread pode ler, escrever ou mudar a pilha de dados de outra thread. Dessa forma, a proteção deve ser implementada na aplicação. As threads podem estar em diferentes estados: - Executando - Bloqueado - Pronto - Finalizado Dadas as características observa-se a seguinte diferença quanto ao conteúdo das threads e processos: 2 SISTEMAS DISTRIBUÍDOS Prof. Ricardo Rodrigues Barcelar http://www.ricardobarcelar.com.br Quadro 1 – Itens da Thread e do Processo Itens por Thread Itens por Processo Espaço de endereçamento Variáveis Globais Arquivos abertos Processos filhos Sinais Timers Informações da Conta Semáforos PC Pilha Registradores Threads Filhas Estado 3.1.1. VANTAGENS - Explorar paralelismo ao executar um programa em um sistema multiprocessador. Ex.: Cada thread é designado a uma CPU, enquanto dados compartilhados são armazenados em memória compartilhada. - Em grandes aplicações, desenvolvidas como um conjunto de programas cooperativos evita chaveamento entre diferentes processos devido comunicação através de Interprocess Communication (IPC). Figura 2 - Chaveamento de contexto como resultado de IPC Nas threads a comunicação pode ser feita com a utilização de dados compartilhados. O chaveamento ocorre entre espaços de usuário. 3.1.2. IMPLEMENTAÇÃO DE THREADS EM SISTEMAS NÃO-DISTRIBUÍDOS Nível Usuário - As threads rodam sobre o runtime system – coleção de procedimentos que gerenciam as threads. 3 SISTEMAS DISTRIBUÍDOS Prof. Ricardo Rodrigues Barcelar http://www.ricardobarcelar.com.br - Quando uma thread executa uma chamada de sistema, ela entra no estado de espera e opera um semáforo enquanto o runtime system verifica se o thread deve ser suspensa. - Existe um custo de criação e alocação da memória para a pilha. - Chaveamento de contexto de thread pode ser feito em apenas algumas instruções. Não há necessidade de mudar mapas de memória, descarregar o TLB (Translation Lookaside Buffer) - As threads precisam entrar em sincronia. Figura 3 - Implementação em nível de usuário A desvantagem de threads de nível de usuário está em como chamadas de sistemas bloqueantes são implementadas, como por exemplo, ler um pipe vazio, na qual a chamada de sistema acarretará em bloqueio de todas as threads. Nível Kernel - A criação, encerramento e sincronização deverão ser feitos pelo kernel. - Chamadas de sistema deverão ser realizadas. - Chavear contextos de threads é tão caro quanto chavear contexto de processos. Figura 4 - Implementação em nível do Kernel 4 SISTEMAS DISTRIBUÍDOS Prof. Ricardo Rodrigues Barcelar http://www.ricardobarcelar.com.br 3.2. Threads em Sistemas Distribuídos Na implementação de threads em sistemas distribuídos uma importante propriedade é que eles podem proporcionar um meio conveniente de permitir chamadas bloqueantes de sistema sem bloquear o processo inteiro. As threads são particularmente atraentes para utilização em sistemas distribuídos, pois facilitam a comunicação na forma de manter múltiplas conexões lógicas ao mesmo tempo. 3.2.1. CLIENTES MULTITHREADS Os Sistemas distribuídos que operam em redes de longa distância escondem longos tempos de propagação de mensagens entre processos. A maneira de ocultar latências de comunicação é iniciar a comunicação e imediatamente prosseguir com outra atividade. Em um browser web, o documento Web consiste em um texto, imagens, ícones, etc. Cada elemento, browser estabelece uma conexão TCP/IP, para ler os dados e passar ao monitor do usuário. Operações bloqueadoras fazem o estabelecimento da conexão e leitura de dados. Os browsers começam a exibir dados enquanto, à medida que novas informações chegam. Enquanto o texto está sendo disponibilizado para o usuário, incluindo as facilidades de rolamento, o browser continua buscando outros arquivos, como imagens. A vantagem é que o usuário não precisa esperar até que todos os componentes sejam buscados. Threads separados são ativados para se encarregar de buscar diferentes partes de uma página, assim caso o servidor esteja em sobrecarga, ter um cliente multithread possibilita estabelecer conexões com diferentes servidores, permitindo transmissão dos dados em paralelo, onde o cliente pode manipular fluxos de dados de entrada em paralelo, por meio de threads. 3.2.2. SERVIDORES MULTITHREADS Um servidor de arquivos normalmente espera pela entrada de uma requisição para uma operação de arquivo e, na seqüência, executa a requisição e então devolve a resposta. Com a utilização de threads é possível aumentar seu desempenho. Os servidores multithreads funcionam da seguinte maneira: - requisições são enviadas por clientes para uma porta no servidor. - Uma thread despachante lê requisições que entram para uma operação de arquivo. - O servidor escolhe uma thread operária. - Se o thread escolhido estiver suspenso, outro thread é selecionado para ser executado, como por exemplo, o thread despachante pode ser selecionado para adquirir mais trabalho. 5 SISTEMAS DISTRIBUÍDOS Prof. Ricardo Rodrigues Barcelar http://www.ricardobarcelar.com.br Figura 5 - Servidor multithread organizado segundo modelo despachante/operário Se o servidor é inteiramente CPU-bound, não existe necessidade de diversos threads, ocorre um aumento de complexidade sem ganho de desempenho. 4. VIRTUALIZAÇÃO Threads e processos podem ser vistos como um modo de fazer diversas tarefas ao mesmo tempo. Em computadores monoprocessados, a execução simultânea é uma ilusão, pois possuem uma única CPU, ou seja, somente uma instrução de um único thread ou processo será executada por vez. A virtualização de recursos possibilita “fingir” que um determinado recurso está replicado no sistema. Dessa forma, estende ou substitui uma interface existente de modo a imitar o comportamento de outro sistema. Figura 6 - (a) Organização geral entre Programa, Interface e Sistema. (b) Organização geral da virtualização do sistema A sobre o B Na década de 1970 a virtualização foi aplicada com sucesso nos mainframes IBM, que ofereciam uma máquina virtual para executar softwares que incluíam aplicações e também os sistemas operacionais. 6 SISTEMAS DISTRIBUÍDOS Prof. Ricardo Rodrigues Barcelar http://www.ricardobarcelar.com.br Softwares em nível mais alto são mais estáveis que o hardware e sistemas de software de baixo nível. Assim a virtualização pode ajudar transportando as interfaces de softwares para novas plataformas. As novas plataformas são capazes de executar softwares existentes anteriormente. 4.1. Arquiteturas de Máquinas Virtuais Existem vários modos pelos quais a virtualização pode ser realizada na prática. Existem quatro tipos diferentes de interfaces em quatro níveis diferentes como representado na figura a seguir: Figura 7 - Várias interfaces oferecidas por sistemas de computadores A essência da virtualização é imitar o comportamento das interfaces (instruções de máquina, chamadas de sistema). 4.2. Máquina Virtual de Processo Aplicações desenvolvidas para um Sistema Operacional são executadas em outro Sistema Operacional. A virtualização é feita somente para um único processo. Funcionam como emuladores, com a finalidade de imitar chamadas de sistema. 4.3. Monitor de Máquina Virtual Fornece o conjunto de instruções completo do hardware. Vários sistemas operacionais diferentes executando independente e concorrentemente na mesma plataforma. Importantes no contexto de confiabilidade e segurança proporcionando isolamento de uma aplicação e seu ambiente. As falhas não afetam a máquina inteira. Exemplo: VMware, VirtualBox, VitualPC, etc. 7 SISTEMAS DISTRIBUÍDOS Prof. Ricardo Rodrigues Barcelar http://www.ricardobarcelar.com.br Figura 8 - (a) Máquina Virtual de processos com várias aplicações (instâncias). (B) Monitor de Máquina Virtual com várias aplicações (instâncias) 5. CLIENTES E SERVIDORES Uma tarefa muito importante de máquinas clientes é proporcionar aos usuários meios de interagir com servidores remotos. Isto pode se dar de duas formas: - Para cada serviço remoto, a máquina cliente terá um servidor separado, com o qual possa estabelecer contato. Algumas operações são feitas no próprio cliente. - Fornecer apenas uma interface de usuário conveniente. Máquina cliente é usada somente como um terminal sem nenhuma necessidade de armazenamento. Figura 9 - Soluções cliente-servidor 5.1. Transparência na Distribuição no Cliente O software no lado cliente pode ser mais do que uma interface. Em alguns casos, parte do nível de processamento e dados são executadas no lado cliente. 8 SISTEMAS DISTRIBUÍDOS Prof. Ricardo Rodrigues Barcelar http://www.ricardobarcelar.com.br 5.1.1. TRANSPARÊNCIA DE MIGRAÇÃO Se um cliente já está vinculado a um servidor, ele pode ser informado quando o servidor mudar de localização. Um Middleware no cliente oculta do usuário a corrente localização do servidor. 5.1.2. TRANSPARÊNCIA A FALHA O Middleware cliente pode ser configurado para tentar a conexão com um servidor repetidas vezes, ou tentar outro servidor após várias tentativas. O uso de cachê minimiza uma falha na conexão com o servidor. 5.2. Servidores 5.2.1. QUESTÕES DE PROJETO Cada servidor é organizado do mesmo modo: - Espera por uma requisição de um cliente. - Assegura o atendimento. - Espera pela próxima requisição. 5.2.2. TRATAMENTO DE REQUISIÇÕES Em um Servidor Iterativo, o próprio servidor manipula a requisição e, se necessário, retorna uma resposta ao cliente. Um Servidor Concorrente não manipula por si próprio a requisição. Como nos servidores multithreads e processos ou threads que devolvem a resposta ao cliente. 5.2.3. REQUISIÇÃO DO CLIENTE Clientes enviam requisições a uma porta, na máquina em que o servidor está executando Para alguns serviços conhecidos (FTP,HTTP) existem portas pré-definidas. Para serviços que não requerem porta pré-determinada, uma opção é ter um daemon, onde o cliente o acessa e o sistema operacional informa dinamicamente uma porta. Outra maneira de manipular portas é o uso de superservidores. Para os casos onde diversos servidores que possuem uma porta específica estão rodando em uma mesma máquina. O monitoramento passa a ser realizado por um superservidor à escuta em cada porta associada com um serviço específico. Exemplo é o daemon inetd no Unix. 9 SISTEMAS DISTRIBUÍDOS Prof. Ricardo Rodrigues Barcelar http://www.ricardobarcelar.com.br Figura 10 - (a) Daemon. (b) Supervisor 5.2.4. INTERROMPENDO A COMUNICAÇÃO Na abordagem mais simples o usuário sai abruptamente da aplicação cliente. O servidor encerrará a conexão antiga. Na abordagem mais completa são usados os dados “urgentes” (fora da banda). Pacotes TCP possuem no header o campo URG. O servidor ao receber um pacote com o campo URG setado é interrompido, através de um sinal. 5.2.5. MANUTENÇÃO DE ESTADO São três os estados: - Sem estado - Estado flexível - Com estado 5.2.5.1. Servidores sem estado: Não mantém informações sobre os estados dos clientes e podem mudar seu próprio estado sem ter de informar a nenhum cliente, como por exemplo, o Servidor Web que, após processar uma requisição, esquece o cliente. Mesmo sem estado, servidor Web guarda informações de clientes. A perda não resulta na interrupção do serviço. 10 SISTEMAS DISTRIBUÍDOS Prof. Ricardo Rodrigues Barcelar http://www.ricardobarcelar.com.br 5.2.5.2. Servidores com estado flexível: Servidor promete manter estado em nome do cliente, por um tempo limitado. Após o tempo limitado, o servidor descarta estas informações. Exemplo: Servidor promete manter um cliente informado sobre atualizações. 5.2.5.3. Servidores com estado: O servidor mantém as informações persistentes sobre seus clientes. As informações precisam ser explicitamente removidas pelo servidor. Exemplo: Servidor de arquivos que permite a um cliente manter cópia local de um arquivo. O servidor mantém uma tabela, com entradas (cliente, arquivo). Permite monitorar as permissões sobre um arquivo, etc. O problema aqui é a recuperação de Falhas. 6. MIGRAÇÃO DE CÓDIGO Além a passagem de dados entre diferentes máquinas, em alguns casos é importante migrar código de uma máquina para outra. A principal razão em se fazer a migração de código é obter um aumento de desempenho. 6.1. Desempenho O envio de processos de máquinas sobrecarregadas para máquinas com cargas mais leves evita grande quantidade de mensagens trocadas entre aplicações cliente-servidor. Exemplos: - Operações de banco de dados que envolvem uma grande quantidade de dados (aplicação cliente/servidor) - Formulários enviados do servidor para o cliente. 6.2. Modelos para Migração de Código A migração de código é algo muito mais amplo: podemos também migrar status de um programa, sinais pendentes e outras partes do ambiente. Um processo consiste em três segmentos: - Segmento de código: contém o conjunto de instruções que compõem o programa que está em execução. - Segmento de recursos: contém referências a recursos externos (arquivos, impressoras). -Segmento de execução: armazenar o estado em execução de um processo no momento da migração (dados privados, pilha, contador de programa). A mobilidade pode ser de dois tipos: - Mobilidade Fraca: possível transferir somente o segmento de código, junto com alguns dados de inicialização. Requer somente que a máquina-alvo possa executar o código (portabilidade). 11 SISTEMAS DISTRIBUÍDOS Prof. Ricardo Rodrigues Barcelar http://www.ricardobarcelar.com.br - Mobilidade Forte: segmento de execução também pode ser transferido. O processo em execução pode ser parado e movido para uma outra máquina e retomar a execução no ponto original. Em relação do ponto de início da migração: - Iniciada pelo remetente: a migração é iniciada na máquina em que o código está em execução no momento em questão. Exemplo é enviar programa de busca pela Internet a um servidor de banco de dados para realização de pesquisas. - Iniciada pelo destinatário: Iniciativa da migração de código é tomada pela máquina-alvo. Figura 11 - Alternativas para migração de código 6.3. Migração e Recursos Locais Segmentos de recursos requerem uma atenção especial. Exemplo: A comunicação de um processo sendo feita através de uma porta TCP. Ao mudar de localização, este processo deverá devolver a porta e requisitar uma nova no destino. Existem três tipos de vinculações do processo-recurso: - Vinculação por identificador: o processo requer exatamente o recurso referenciado (URL de um site). - Vinculação por valor: É necessário somente um valor. Se outro recurso fornece o mesmo valor, execução não é afetada (bibliotecas padronizadas) - Vinculação por tipo: Processo requer um recurso de um tipo específico (monitores, impressoras). Existem também três tipos de vinculações recurso-máquina: - Recursos não ligados: recursos podem ser movidos com facilidade entre maquinas diferentes (arquivos de dados). 12 SISTEMAS DISTRIBUÍDOS Prof. Ricardo Rodrigues Barcelar http://www.ricardobarcelar.com.br - Recursos amarrados: recursos podem ser movidos ou copiados, mas só a custo relativamente alto (banco de dados locais). - Recursos fixos: recursos estão intimamente vinculados a uma máquina ou ambiente especifico e não podem ser movidos (porta). - Referência global: Caso vários processos referenciem um recurso, uma alternativa é estabelecer uma referência global, que atravesse as fronteiras das máquinas. Exemplo: URL (baixa complexidade), Memória compartilhada entre processos (referência global significa memória compartilhada). Pode haver várias combinações entre vinculação processo-recurso e recurso-máquina. Exemplos: - Processo admite que a memória pode ser compartilhada entre processos (recurso fixo, vinculação de valor). - Bibliotecas de tempo de execução (recurso amarrado, vinculação de valor). A complexidade está ligada aos tipos de vínculo processo-recurso e recurso-máquina. - Recursos não ligados: Melhor solução é copiar ou mover o recurso para o novo destino. - Vinculações por tipo: A solução é vincular novamente o processo a um recurso do mesmo tipo disponível no local. 6.4. Migração em Sistemas Heterogêneos A migração em sistemas heterogêneos requer segmento de código que possa ser executado em cada plataforma e um segmento de execução pode ser adequadamente representado em cada plataforma. O efeito global é migrar sistema operacional inteiro, em vez de migrar processos. 13