Sincronização entre Processos -Capitulo 3
Introdução
O problema do processo do sincronização surge da necessidade de partilhar recursos num sistema de computação. Esta partilha exige coordenação e cooperação para garantir o sucesso da operação.
Um exemplo pode ilustrar alguns destes aspectos: Exemplo de uma hamburgueria.
Fazemos um x pedido ao garçon, ele coloca o x pedido numa mesa rotativa.
O empactador tira as ordens da mesa rotativa e coloca os itens pedidos dentro de 1 saco entregando-o ao caixa. Este por sua vez processa os sacos, um de cada vez, recebendo o dinheiro e entregando o que foi pedido.
Além destes trabalhadores existe ainda o cozinheiro a trabalhar continuamente abastecer os hamburgueres cozinhados ao embalador .
Neste exemplo, cada processo ( cada pessoa ) opera de uma forma independente. A única comunicação que existe é em certas áreas comuns: a ordem na mesa rotativa, na caixa registadora.
Este exemplo simples ilustra formas de comunicação e de cooperação que é frequentemente dado como garantido. O empactador só pode continuar a desempenhar as suas funções se existirem um pedido.
O que acontece se durante 1 largo período não existirem pedidos para serem atendidos ? Vai dormir?
E como é que ele é avisado quando chega um cliente.? O garçon dá-lhe um toque e acorda-o! É um exercício útil de procurar outras formas de comunicação e cooperação. Por exemplo: O que evita que o cozinheiro enterre o garfo debaixo de uma pilha de hamburguer durante um periodo de tempo?
Análogas situações existem num sistema de computação entre processos. Em alguns casos a coordenação é forçada sobre eles pelo sistema operativo devido a escassez de recursos como por exemplo a necessidade de esperar pelo o acesso a um canal I\O Noutros casos uma tarefa simples pode consistir numa serie de processos que trabalham todos juntos. Um sistema de informação tipo serviço de reservas de uma companhia aérea pode Ter diversos processos realizando tarefas separadas como no caso da hamburgueria.
A tarefa pode aceitar pedidos, verificar inputs, enviar o pedido para o processo "executor". O processo executor acede aos dados para procurar a informação necessária e manda-la para o processo de "output". O processo de output envia a resposta para o solicitador original.
regresso ao inicio da pagina
Os Processos no Modelo Computacional
A criação e a eliminação de processos são funções indispensáveis no modelo computacional. Geralmente os processos organizam-se de acordo com uma hierarquia, a partir de um processo pai. Esta hierarquia traduz-se por informações que são mantidas no contexto dos processos de forma a poder gerir, em conjunto, o processo e os respectivos descendentes. Por exemplo, em alguns sistemas a terminação de um processo elimina todos os seus filhos, noutros os processos filhos mantêm-se activos.
A estrutura hierárquica dos processos facilita a função de criação, dado que grande parte do ambiente de execução pode ser herdada do contexto processo pai.
A função de criação de um processo começa por reservar um contexto para o processo, preenche-o de acordo com os parâmetros fornecidos pelo utilizador ou implicitamente herdados do contexto processo pai. O utilizador ou o sistema deverá atribuir uma prioridade em função da qual o processo será colocado na lista de executáveis.
A função de criação tem como resposta a identificação interna do processo que constitui a referência que permitirá designá-los nas primitivas onde seja necessária uma identificação explicita.
Quando for seleccionado para execução, iniciar-se-á a partir da primeira instrução especificada no ficheiro que contem o programa executável .A primitiva de eliminação retira o processo de execução e liberta o contexto e recursos por ele detidos.
regresso ao inicio da pagina
Mecanismos de Sincronização
Determinadas aplicações só podem ser eficientemente implementadas quando suportadas por diversas actividades independentes. A decomposição do algoritmo em actividades paralelas permite também esperar obter um melhor desempenho global da aplicação. Contudo, não podemos esquecer que as actividades nunca são totalmente independentes, tendo de se sincronizar para poderem executar um algoritmo global comum. Existem diversos motivos que justificam a necessidade de sincronizar explicitamente a actividade dos processos.
Para simplificar a sua analise agrupámo-los em três categorias:
Cooperação: Esta forma de sincronização é a mais óbvia e resulta da necessidade de interacção entre diversas actividades para executarem uma aplicação comum. A situação mais simples é a de um processo que apenas poderá prosseguir depois de outro ter executado uma determinada operação. É o que se passa no exemplo da introdução.
Os mecanismos de sincronização devem permitir que um processo se bloqueie á espera de um acontecimento que lhe será assinalado implicitamente quando for desbloqueado.
Competição por um recurso: A competição pela obtenção de um recurso único ou limitado impõem também a necessidade de mecanismos de sincronização. A competição tem de ser resolvida de forma a garantir que o recurso seja utilizado de forma consistente pelos processos envolvidos.
O recurso pode assumir diversas formas, como sejam um periférico que deve ser utilizado em exclusividade ou um ficheiro onde se pretende escrever. O recurso não necessita de ser único, podendo ser constituído por um conjunto de unidades que servirão um numero idêntico de pedidos. Os processos podem requisitar, dinamicamente, blocos de memória. A memória que é possível distribuir é finita, pelo que apenas um determinado número de pedidos pode ser satisfeito.
Os processos que não disponham dos recursos necessários para prosseguir a execução têm de ser bloqueados num mecanismo de sincronização até que a condição de bloqueio deixe de ser válida.
Exclusão Mútua: A necessidade de exclusão não é tão obvia como as anteriores tendo origem no mecanismo de multiplexagem do processador que suporta a execução dos processos.
Quando analisamos um programa, consideramos que a modificação de uma variável apenas se pode efectuar por atribuição explicita de um valor. Contudo, num ambiente concorrente tal asserção pode não ser valida se a variável for acedida por mais de um processo. Suponhamos, por exemplo, um processo que testa a variável, e em função do valor decide modificá-la . Pode suceder que o outro processo, que entretanto se executa em paralelo, decida também modificá-la. A execução do programa torna-se inconsistente, dado que sucedeu algo não previsto no modelo de programação. A variável mudou de valor através de uma acção exterior.
Na programação concorrente a utilização de variáveis partilhadas implica precauções suplementares que obrigam a sincronizar os acessos dos processos que as pretendem modificar.
A exclusão mútua pode ser considerada como um caso particular da competição por um recurso, o acesso exclusivo a uma estrutura de dados. Contudo, devido á sua importância nuclear em toda a programação concorrente,
regresso ao inicio da pagina
Semáforos
Os semáforos apresentam um mecanismo de sincronização sem espera activa que pode ser adaptado aos diversos problemas de sincronização mencionados através de uma conveniente parametrização da sua variável de controlo.
Os semáforos são constituídos por uma variável de controlo inteira e por uma lista de processos. A primitiva Esperar bloqueia um processo quando a variável do semáforo tem o valor zero. O contexto do processo é colocado na fila de processos do semáforo e o seu estado passa a bloqueado. A primitiva Assinalar incrementa a variável de controlo, se não existirem processos bloqueados, ou torna executável um processo.
A variável do semáforo pode ser considerada como a indicação do numero de recursos disponíveis que o semáforo controla. Quando inicializada com uma unidade, o recurso é único e será utilizado em exclusividade.
Assinalar um acontecimento a um processo pode ser feito de forma directa ou indirecta. No primeiro caso um processo actua directamente sobre o estado de outro, no segundo é utilizada uma estrutura de dados intermédia que implementa a sincronização. A sincronização indirecta ainda se pode subdividir consoante o acontecimento fica ou não memorizado quando o processo a quem é dirigido está ou não a espera. Os mecanismos indirectos com memória são as mais frequentes e são facilmente implementados utilizando semáforos.
regresso ao inicio da pagina
Cooperação entre processos
A cooperação entre processos, na sua forma mais simples, consiste em bloquear um processo Pi até que um processo Pj lhe assinale que uma determinada acção ou acontecimento se produziu. Para sincronizar os dois processos é necessário dispor de um mecanismo independente da velocidade de execução que permita a um processo activo:
Sincronização Directa
A acção directa sobre o estado de um processo é o mecanismo mais simples de sincronização. Um par de primitivas( suspender, Acordar) actua directamente sobre o processo bloqueando-o numa fila de processos suspensos ou acordando-o, o que corresponde a transferi-lo novamente para a fila dos processos executáveis. É vulgar incluir este novo estado no diagrama de estados dos processos, dado que corresponde a nova fila de espera onde o processo pode ser colocado. A sincronização directa implica o conhecimento do identificador do processo sobre o qual se pretende actuar.
Este tipo de sincronização não pode ser de uso geral por 2 razões. Primeiramente não se pode dar aos programas dos utilizadores ( sempre suspeitos) a possibilidade de interferirem com outro utilizadores ou mesmo com o sistema operativo. Têm de existir mecanismos para evitar que um processo possa arbitrariamente suspender outro sobre o qual não detém qualquer privilégio. Uma restrição habitual é apenas permitir o uso de sincronização directa entre processos relacionados hierarquicamente. Esta protecção traduz-se, normalmente por restringir a sincronização directa a processos do mesmo utilizar.
A Segunda razão é de ordem lógica. Na definição do algoritmo de um processo é possível saber que este irá interactuar com outro, mas desconhecer a sua identidade que apenas será definida durante a execução.
Sincronização Indirecta
A sincronização indirecta tem obviamente vantagens, garantido a igualdade de tratamento a todos ao processos com os mesmos privilégios. Podemos subdividi-la em duas categorias
A sincronização indirecta exprime-se com base em semáforos através do conceito de semáforo privado, isto é, se este for o único que executa a operação esperar sobre o semáforo, podendo os restantes processos notifica-lo de um acontecimento através da primitiva assinalar.
regresso ao inicio da pagina
Sincronização no Modelo Computacional
O modelo computacional tem que ser completado com os mecanismos de sincronização entre processos. Normalmente os sistemas oferecem primitivas para a sincronização directa que, apenas podem ser utilizadas entre processos relacionados hierarquicamente. Este mecanismo traduz-se por uma primitiva que bloqueia o processo numa fila de processos suspensos e outra que permite acordá-lo.
Suspender
Acordar
Por vezes este mecanismo é complementado pela possibilidade de especificar uma temporização que permite a um processo auto-suspender-se durante um determinado intervalo tempo.(adormecer)
Adormecer
Todos os sistemas dispõem de algum mecanismo para implementar a sincronização indirecta entre processos, que consiste em bloquear os processos que executam esperar e, autorizam a passagem de todos os processos. Dado que os semáforos permitem implementar os modelos de sincronização e como os restantes objectos do sistema possuem primitivas para criar eliminar semáforos. Na primitiva se criação é especificado o valor inicial da variável semáforo
IdSemaforo:= CriarSemaforo ( valor inicial)
EliminarSemaforo (IdSemaforo)
As primitivas Assinalar e Esperar podem ter diversas formas, das quais as mais interessantes são as que permitem receber ou enviar um numero de unidade diferente de 1 e as que a permitem especificar um tempo máximo de bloqueio no semáforo.
Esperar (IdSemaforo)
Assinalar (IdSemaforo)
regresso ao inicio da pagina