Baixe o app para aproveitar ainda mais
Prévia do material em texto
SINCRONIZAÇÃO E COMUNICAÇÃO ENTRE PROCESSOS Os sistemas multiprogramáveis possibilitaram estruturar aplicações de maneira que diferentes parte do código do programa pudessem executar concorrentemente, através de múltiplos processos ou threads. Em um sistema multiprogramável com um processador, os processos alternam sua execução segundo critérios de escalonamento estabelecidos pelo sistema operacional. Em sistema com múltiplos processadores, a possibilidade do paralelismo na execução de instruções somente estende as vantagens que a programação concorrente proporciona. É natural que processos de uma aplicação concorrente compartilhem recursos do sistema, como arquivos, registros, dispositivos de E/S e áreas de memória. Este compartilhamento de recursos pode ocasionar em situações indesejáveis, capazes até mesmo de comprometer a execução das aplicações. Para evitar este tipo de problemas, processos concorrentes devem ter suas execuções sincronizadas, a partir de mecanismos oferecidos pelo SO, com o objetivo de garantir o processamento correto dos programas. Aplicações concorrentes Muitas vezes é necessário que os processos de comuniquem entre si. Esta comunicação pode ser implementada através de diversos mecanismos, como variáveis compartilhadas na memória principal ou troca de mensagens. Na imagem abaixo, dois processos (pode ser subprocessos ou threads) concorrentes compartilham um buffer para trocar informações através de processos de leitura e gravação. O buffer só poderá ser lido se existir alguma coisa nele, e só é possível gravar algo no buffer se ele estiver vazio. Os processos devem aguardar até que o buffer esteja pronto para alguma operação. Mecanismos que garantem a comunicação entre processos concorrentes e a recursos compartilhados são chamados de “mecanismos de sincronização”. Especificação de concorrência em programas Existem várias notações para especificar a concorrência entre programas, ou seja, partes de um programa que devem ser executadas concorrentemente. Alguns comandos conseguem fazer com que uma sequência de instruções sejam executadas concorrentemente até um certo ponto. Por exemplo, a fórmula abaixo pode ter três instruções executadas concorrentemente: X = RAIZ(1024) + (124 * 45) - (105 / 42) 1 3 4 5 6 1. Quais instruções podem ser executadas concorrentemente? 2. Qual instrução tem que esperar a execução de outras? Problemas de compartilhamento de recursos Para a compreensão de como a sincronização entre processos concorrentes é fundamental para a confiabilidade dos sistemas multiprogramáveis, veremos dois exemplos de problemas de compartilhamento de recursos. 1. Dois processos concorrentes de 2 caixas para atualizar o saldo de um cliente, um para sacar e um para depositar. 2. A execução de duas operações alterando o valor de uma variável, +1 e -1. Analisando estes dois exemplos, é possível concluir que em qualquer situação onde dois ou mais processos compartilham recursos, devem existir mecanismos de controle para evitar esses tipos de problemas, conhecidos como “condições de corrida”. Exclusão Mútua Uma solução simples para evitar esses tipos de problema é impedir que dois ou mais processos acessem um mesmo recurso compartilhado simultaneamente. Enquanto um processo estiver acessando determinado recurso, todos os outros que querem acessá-lo devem esperar pelo término da utilização do recurso. Essa ideia é chamada de “exclusão mútua”. A exclusão mútua deve afetar somente os processos concorrentes quando um deles estiver fazendo o uso do recurso compartilhado. A parte do código onde é feito acesso ao recurso compartilhado é denominada de “região crítica”. Desta forma, é possível evitar problemas decorrentes do compartilhamento. Os mecanismos que implementam a exclusão mútua utilizam protocolos de acesso a regiões críticas. Toda vez que um processo desejar executar instruções de suas regiões críticas, obrigatoriamente deverá executar antes um protocolo de entrada nessa região. Dessa mesma forma, ao sair da região crítica um protocolo de saída deverá ser executado. Assim, como ficaria o funcionamento do programa com aqueles dois processos para alterar o saldo de um cliente? Diversas soluções de hardware e de software foram propostas, e existem, para garantir a exclusão mútua de processos concorrentes. Sincronização condicional Sincronização condicional é uma situação em que o acesso ao recurso compartilhado exige a sincronização de processos vinculada a uma condição de acesso. Um recurso pode não se encontrar pronto para uso devido a uma condição específica. Nesse caso, o processo que deseja acessá-lo deverá permanecer bloqueado até que o recurso fique disponível. Exemplo da imagem do buffer, os dois processos devem estar sincronizados para que um não tente gravar dados no buffer cheio ou realizar uma leitura em um buffer vazio. Semáforos O conceito de semáforos foi proposto por Dijkstra em 1965 como um mecanismo de sincronização de processos, permitindo de forma simples implementar a exclusão mútua e a sincronização condicional. Atualmente, a maioria das linguagens de programação disponibiliza rotinas para o uso de semáforos. Um semáforo é uma variável inteira não negativa que só pode ser manipulada por duas instruções: DOWN e UP. A instrução UP incrementa o valor de um semáforo enquanto o DOWN decrementa. Os semáforos podem ser considerados como binários (0 ou 1) ou contadores (0, 1, 2, ..., n). Exclusão mútua usando semáforos Sincronização condicional usando semáforos Pode usar os dois tipos de semáforos. Por exemplo, o binário pode indicar se o buffer está cheio ou vazio, enquanto o contador pode dizer qual é a posição do buffer que está vazia para escrita ou cheia para ser lida. Monitores São mecanismos de sincronização de alto nível que tornam mais simples o desenvolvimento de aplicações concorrentes. A maioria da linguagens de programação também disponibilizam rotinas para o uso de monitores. O monitor é formado por procedimentos e variáveis encapsuladas dentro de um módulo. Sua característica mais importante é a implementação automática da exclusão mútua entre os processos declarados, ou seja, somente um processo pode estar executando um dos procedimentos do monitor em um determinado instante. Se o monitor estiver em uso por um processo, os demais que tentarem acessá-lo ficarão em uma fila de entrada. As variáveis são visíveis apenas aos procedimentos. Troca de mensagens Troca de mensagens é um mecanismo de comunicação e sincronização entre processos. O SO possui um subsistema de mensagens que suporta este mecanismo sem a necessidade do uso de variáveis compartilhadas. Para que exista uma comunicação entre processos deve haver um canal de comunicação, que pode ser um buffer ou um link de uma rede de computadores. A troca de mensagens entre processos pode ser implementada de duas formas: comunicação direta e indireta. A comunicação direta exige que seja informada junto com a mensagem o nome do processo receptor ou transmissor. Dessa forma, a troca de mensagens pode ocorrer somente entre dois processos. A comunicação indireta utiliza uma área compartilhada, ode as mensagens podem ser colocadas pelo processo transmissor e retiradas pelo processo receptor. Este tipo de buffer pode ser também chamado de mailbox. Assim, vários processos podem estar ligados a uma mailbox. Deadlock É uma situação em que um processo aguarda um recurso que nunca estará disponível ou um evento que nunca ocorrerá. Essa situação é consequência, na maioria das vezes, do compartilhamento de recursos, como dispositivos, arquivos e registros, entre processos concorrentes em que a exclusão mútua é exigida. Este problema torna-se mais frequente e crítico na medida em que SO evoluem no sentido de implementar o paralelismo de forma intensiva. Para que ocorra a situação do deadlock, quatro condições são necessárias simultaneamente: 1. Exclusão mútua: cada recurso só pode estar associado a um único processo em determinado instante; 2. Espera por recurso:um processo, além de recursos já alocados, pode estar esperando por outros recursos; 3. Não preempção: um recurso não pode ser liberado só porque outros processos desejam o mesmo recurso; 4. Espera circular: um processo pode ter de esperar por um recurso alocado a outro processo, e vice-versa. Prevenção de deadlock Para prevenir a ocorrência de deadlock é necessário que uma das quatro condições apresentadas nunca se satisfaça. Para a exclusão mútua já vimos algumas possíveis maneiras de implementação. Para a segunda, processos que já possuam recursos garantidos não devem requisitar novos recursos. Para a terceira, o SO deve permitir que recursos sejam retirados de processos no caso de outros processos requisitarem o mesmo recurso. Não tratado de maneira correta, pode trazer uma série de problemas. Para a quarta, deve-se garantir que um processo só terá um recurso alocado a ele por vez. Se precisar de outro, deve liberar o que está em uso. Detecção de deadlock Para detectar deadlocks, o SO deve manter estruturas de dados capazes de identificar cada recurso do sistema, os processos que estão alocados e os que estão a espera da liberação de recursos. Correção do deadlock Uma solução simples é simplesmente eliminar um ou mais processos envolvidos no deadlock e liberar os recursos alocados à eles. O OS deve ter cuidado com isso, pois se o processo estiver atualizando um arquivo ou realizando uma impressão, os recursos devem ser corretamente liberados para que outros processos continuem a executar. A eliminação é feita de forma aleatória ou conforme a prioridade do processo. Uma solução menos drástica seria liberar apenas alguns recursos alocados a alguns processos, até que o ciclo termine. Referências MACHADO, Francis B.; MAIA, Luiz P. Arquitetura de Sistemas Operacionais. 4. ed. Editora LTC, 2011. SINCRONIZAÇÃO E COMUNICAÇÃO ENTRE PROCESSOS Aplicações concorrentes Especificação de concorrência em programas Problemas de compartilhamento de recursos Exclusão Mútua Sincronização condicional Semáforos Monitores Troca de mensagens Deadlock Prevenção de deadlock Referências
Compartilhar