Início | Currículo | CCO | Fotos | SCI | Mural | Links

VOLTAR
Grupo:

Alexandre de Mari
Kimie Nakahara

Domínio

Em alguns sistemas operacionais, processos que estão trabalhando juntos podem compartilhar algum armazenamento comum que cada um pode ler e gravar. Situações como essa, em que dois ou mais processos estão lendo ou gravando alguns dados compartilhados, e o resultado final depende de quem executa precisamente quando, são chamadas de condições de corrida[1].

Neste contexto, o domínio a ser analisado é o sincronismo de processos em sistemas operacionais. O sincronismo é necessário para um adequado seqüenciamento quando estão presentes dependências do tipo: se o processo A produz dados e o processo B os imprime, B tem de esperar até que A tenha produzido alguns dados antes de começar a imprimir[1].

Uma possível família deste domínio seria o Sincronizador.

A Família Sincronizador

Para evitar as condições de corrida é necessário encontrar uma maneira de proibir que mais de um processo leia e grave os dados compartilhados ao mesmo tempo. Em outras palavras, precisamos de exclusão mútua. A escolha das operações primitivas apropriadas para obter a exclusão mútua é uma questão de projeto importante em qualquer sistema operacional[1].

A parte do programa em que a memória é compartilhada é chamada de região critica.

Foram feitas várias propostas para obter a exclusão mútua.

Em 1965, Dijkstra sugeriu utilizar um novo tipo de variável chamado semáforo. Ele propôs ter duas operações p e v. A operação p em um semáforo verifica se o valor é maior que 0. Se for, ele diminui o valor e simplesmente continua. Se o valor for 0, o processo é colocado para dormir sem completar o p[1].

Decidimos adotar como membro da Família Sincronizador o Semáforo. Outro membro identificado é o Mutex. Mutex realiza operações de bloqueio e desbloqueio para possibilitar a exclusão mútua.

Hoare (1974) e Brinch Hansen (1975) propuseram uma primitiva de sincronização de nível mais alto chamada monitor. Um monitor é uma coleção de variáveis, de procedimentos e de estruturas de dados que são agrupadas em um tipo especial de módulo ou de pacote. Os processos podem chamar os procedimentos em um monitor sempre que quiserem, mas eles não podem acessar diretamente as estruturas de dados internas do monitor a partir de procedimentos declarados fora do monitor[1].

Os monitores são uma construção de linguagem de programação, de modo que o compilador sabe que eles são especiais e pode gerenciar chamadas para procedimentos do monitor diferentemente de outras chamadas de procedimento. O compilador deve reconhecê-los e arranjar a exclusão mútua de algum modo. C, Pascal e a maioria das linguagens não têm monitores, então, não é razoável esperar que seus compiladores implementem qualquer regra de exclusão mútua[1].

Outro problema com monitores e também com semáforos é que eles foram projetados para resolver o problema de exclusão mútua em uma ou em mais CPUs que têm acesso a uma memória comum. Colocando semáforos na memória compartilhada e protegendo-os com instruções TSL, pode-se evitar as condições de corrida. Quando um sistema consiste em múltiplas CPUs, distribuídas, cada uma com sua própria memória privada, conectadas por uma rede local, essas primitivas tornam-se inaplicáveis[1].

Monitores separam o conceito de exclusão mútua e sincronização condicional, de forma que possuem lock mutuamente exclusivo e zero ou mais variáveis condicionais para gerenciar o acesso concorrente aos dados.

Por ter características que diferem das de Semaphore e Mutex, optamos por criar um membro Monitor para a família.

Uma outra situação considerada ocorre quanto vários processos esperam que uma determinada condição se torne positiva para que possam continuar sua execução. Para modelar esta situação existe o membro Condition: na necessidade de esperar que uma determinada condição se torne verdadeira, um processo invoca o método wait, que colocará este processo para dormir. Todos os processos suspensos serão acordados pelo método broadcast.

Aspectos

Analisando a família dos sincronizadores já existentes no EPOS e também o domínio de sincronismo em sistemas operacionais, concordamos com a presença dos aspectos Remote e Atomic nesta família.

Em um semáforo, por exemplo, verificar o valor, alterá-lo e, possivelmente,  ir dormir é tudo feito como uma ação atômica.É garantido que uma vez que uma operação de semáforo iniciou, nenhum outro processo acesse o semáforo até que a operação tenha se completado ou tenha sido bloqueada. Essa atomicidade é absolutamente essencial para resolver problemas de sincronização e para evitar condições de corrida, justificando assim a presença do aspecto Atomic.

A execução remota de processos, assim como a invocação remota de objetos, pode ser implementada modelando-se o mecanismo necessário para tanto como um aspecto, visto que a característica "remoto" pode existir ou não, e se aplica não só a sincronizadores como também a outras entidades que tratam da coordenação entre processos, como portas de comunicação.

O aspecto Remote provê um mecanismo de invocação remota às abstrações pertencentes à família dos sincronizadores, que quando utilizadas em cenários distribuídos oferecem uma solução centralizada para coordenar processos de aplicações paralelas. Porém este mecanismo não é adequado para coordenação distribuída de processos e pode ser um gargalo numa aplicação paralela, visto que o nó onde o sincronizador se encontra torna-se um ponto por onde todos os processos têm de se comunicar.  Porém, a modelagem de um novo aspecto para a família que resolva este problema é complexa e está fora do escopo deste trabalho.


 


Referências Bibliográficas

[1] - TANNEMBAUM, ANDREW S., WOODHULL, ALBERT S.: Sistemas Operacionais: Projeto e Implementação. 2 ed. Porto Alegre: Bookman, 2000.

[2] - ANTÔNIO AUGUSTO FRÖHLICH: Application-Oriented Operating Systems, Sankt Augustin: GMD - Forschungszentrum Informationstechnik, 2001, 200 p.

VOLTAR