Sistema Operacional Sincronização e Comunicação entre Processos WebDesign Redes de Computadores Aula10_1
Introdução Os processos concorrentes compartilham recursos do sistema (arquivos, registros, dispositivos de E/S e áreas de memória). O compartilhamento de recursos pode causar situações indesejáveis que podem comprometer a execução das aplicações. O sistema operacional oferece mecanismos para sincronização entre os processos concorrentes com o objetivo de garantir o processamento correto dos programas.
Introdução Exemplo: Dado Buffer Processo gravador Leitor Sincronização gravação Leitura Buffer Processo gravador Leitor
Introdução Os dois processos compartilham um buffer para trocar informações. Um processo só poderá gravar dados no buffer se o mesmo não estiver cheio. Um processo só poderá ler dados no buffer caso haja algum dado a ser lido. Os processos deverão aguardar até que o buffer esteja pronto para as operações, seja de gravação, seja de leitura.
Problemas de compartilhamento de recursos Exemplo 1: Compartilhamento de um arquivo em disco Suponha que temos um programa Conta_Corrente que atualiza o saldo bancário de um cliente após o lançamento de débito ou crédito no arquivo de contas correntes Arq_Contas. No arquivo Arq_Contas são armazenados os saldos de todos os correntistas do banco.
Problemas de compartilhamento de recursos Exemplo 1: Compartilhamento de um arquivo em disco O programa lê o registro do cliente no arquivo (Reg_Cliente), lê o valor a ser depositado ou retirado (Valor_Dep_Ret) e, em seguida, atualiza o saldo no arquivo de contas.
Problemas de compartilhamento de recursos Exemplo 1: Compartilhamento de um arquivo em disco PROGRAM Conta_Corrente; . READ(Arq_Contas, Reg_Cliente); READLN(Valor_Dep_Ret); Reg_Cliente . Saldo : = Reg_Cliente . Saldo + Valor_Dep_Ret; WRITE(Arq_Contas, Reg_Cliente); END.
Problemas de compartilhamento de recursos Considere dois processos concorrentes que pertencem a dois funcionários do banco que atualizam o saldo de um mesmo cliente simultaneamente. Analisemos a situação seguinte:
Ao final teríamos um saldo de R$1300,00 ao invés de R$1100,00 Caixa Instrução Saldo arquivo Valor dep/ret Saldo memória 1 READ 1.000 * READLN -200 := 800 2 300 1.300 WRITE
Problemas de compartilhamento de recursos Exemplo 2: Compartilhamento de variável entre dois processos Suponha que o processo A some 1 à variável X e o processo B diminua 1 da mesma variável que está sendo compartilhada. Inicialmente a variável X possui o valor 2. O resultado final de X após a execução dos processos A e B deveria continuar sendo 2.
Problemas de compartilhamento de recursos Exemplo 2: Compartilhamento de variável entre dois processos Processo A Processo B X := X + 1 X := X - 1 Processo A Processo B LOAD X, Ra LOAD X, Rb ADD 1, Ra ADD 1, Rb STORE Ra, X STORE Rb, X
Problemas de compartilhamento de recursos Exemplo 2: Compartilhamento de variável entre dois processos Processo Instrução X Ra Rb A LOAD X. Ra 2 * ADD 1, Ra 3 B LOAD X. Rb SUB 1, Rb 1 STORE Ra, X STORE Rb, X
Problemas de compartilhamento de recursos Situações onde dois ou mais processos estão lendo ou escrevendo algum dado compartilhado e cujos resultados finais dependem das informações de quem e quando executa precisamente são chamadas – condições de disputa. Devem existir mecanismos de controle para evitar esses tipos de problemas.
Exclusão Mútua Solução simples: Se um processo estiver utilizando um dado recurso, os demais processos que queiram utilizá-los deverão esperar pelo término da utilização do recurso. Essa idéia de exclusividade de acesso é chamada de exclusão mútua.
Exclusão Mútua A exclusão mútua afeta os processos concorrentes quando um deles estiver fazendo acesso ao recurso compartilhado. A parte do programa onde é feito o acesso ao recurso compartilhado é denominada região crítica. A execução mutuamente exclusiva, onde dois processos não acessam um recurso compartilhado ao mesmo tempo, evita os problemas de compartilhamento de recursos.
Exclusão Mútua Processo A Processo B T1 T2 T3 T4 Tempo A entra na região crítica A deixa região crítica Processo A B tenta entrar na região crítica B entra na região crítica B deixa a região crítica Processo B B bloqueado T1 T2 T3 T4 Tempo
Exclusão Mútua Os mecanismos que implementam a exclusão mútua utilizam protocolos de acesso à região crítica. Protocolo de entrada – Quando o processo deseja executar instruções na região crítica. Protocolo de saída – Quando o processo sai da região crítica. BEGIN . Entra_Região_Crítica ; (*Protocolo de entrada*) Região_Crítica; Sai_Região_Crítica; (* Protocolo de saída*) END.
Situação indesejável Espera indefinida – É a situação em que um processo nunca consegue executar sua região crítica, e consequentemente, acessar o recurso compartilhado. Quando um recurso é liberado, o S.O. escolhe (aleatoriamente ou baseado em prioridade) um processo, dentre aqueles que aguardam pelo uso do recurso. Ambos os critérios de escolha do processo que acessará o recurso, não garantem que um processo conseguirá acessar o recurso. A espera indefinida pode ocorrer.
Situação indesejável Para impedir este tipo de situação, cria-se filas (FIFOs) de pedidos de alocação para cada recurso. Sempre que um processo solicita um recurso o pedido é colocado no final da fila associada ao recurso. Quando o recurso é liberado, o sistema seleciona o primeiro da fila.
Garantia de exclusão mútua Diversas soluções foram propostas para garantir a exclusão mútua de processos concorrentes. Soluções de hardware Soluções de software Cada proposta tem seus próprios benefícios e problemas.
Solução de Hardware Desabilitação de interrupções A mudança de contexto (troca do processo que utilizará a CPU) é realizada através de interrupções. Na troca de processos, a ocorrência de uma interrupção faz com que o processador salve o contexto de hardware do processo que será interrompido e carregue o contexto de hardware do processo que iniciará sua execução.
Solução de Hardware Desabilitação de interrupções A solução mais simples para o problema da exclusão mútua é fazer com que o processo desabilite todas as interrupções antes de entrar na região crítica e habilite novamente as interrupções ao sair da região crítica. Desta forma, com as interrupções desabilitadas, não poderá haver mudança de contexto, o processo que as desabilitou terá acesso exclusivo garantido.
Solução de Hardware Desabilitação de interrupções BEGIN . Desabilita_Interrupcoes; Regiao_Critica; Habilita_Interrrupcoes; END.
Solução de Hardware Desabilitação de interrupções Problema: Esta solução apesar de simples, apresenta algumas limitações. A multiprogramação (baseada nas interrupções) poderia ficar seriamente comprometida. Se um processo desabilitasse as interrupções e não as habilitasse depois. O processo monopolizaria o processador.
Soluções de Hardware Solução 2: Instrução test-and-set Alguns processadores possuem uma instrução especial test_and_set que tem a função de ler uma variável, armazenar seu conteúdo em uma outra área e atribuir um novo valor à mesma variável. Exemplo: test-and-set(X,Y); A instrução acima, quando executada o valor lógico da variável Y é copiado para X, sendo atribuído à variável Y o valor lógico verdadeiro.
Soluções de Hardware Solução 2: Instrução test-and-set Para coordenar o uso do recurso, a instrução test-and-set utiliza uma variável lógica global. Quando esta variável for falsa, qualquer processo poderá alterar o seu valor para verdadeiro, através da instrução test-and-set e, assim, acessar o recurso de forma exclusiva. Ao terminar o acesso, o processo deve, simplesmente retornar o valor da variável para falso, liberando o acesso ao recurso.
void process_A(void) { bool pode_A; while(1) { pode_A = 1; // Pode_A recebe 1 While( pode_A) // while Pode_A for igual a 1 Test_and_Set ( Pode_A, Bloqueio); Regiao_Critica_A; //entra na região critica_A Bloqueio = false; //libera regiao critica } void process_B(void) { bool pode_B; pode_B = 1; // Pode_B recebe 1 While( pode_B) // while Pode_B for igual a 1 Test_and_Set ( Pode_B, Bloqueio); Regiao_Critica_B; //entra na região critica_B Bloqueio = false; //libera regiao critica int main (void){ bool bloqueio = 0; process_A(); process_B();
Soluções de Hardware O uso de uma instrução especial tem a vantagem da simplicidade de implementação. Mas tem como desvantagem a possibilidade da espera indefinida, pois a seleção do processo que acessará o recurso é feita de forma arbitrária.
Soluções de Software Solução 1: Variáveis de impedimento ( lock variables) Considere que há uma única variável compartilhada (lock), inicialmente contendo o valor 0. Para entrar em sua região crítica, o processo testa antes se há impedimento, verificando o valor da variável lock. Se lock for 0, o processo altera essa variável para 1 e entra na região crítica. Se lock já estiver com valor 1 o processo aguardará até que ela se torne 0.
Soluções de Software Solução 1: Variáveis de impedimento Processo Ação Variável A Lê lock B Modifica valor de lock e entra na região crítica 1 Problema: Os dois conseguiram entrar na região crítica
Soluções de Software Solução 2: Alternância obrigatória Um variável determina de quem é a vez de acessar a região crítica. Os processos alternam no acesso ao recurso. while(TRUE){ while(vez != 0); //laço critical_region(); vez = 1; non critical_region(); } while(TRUE){ while(vez != 1); //laço critical_region(); vez = 0; non critical_region(); } Processo 0 Processo 1
Soluções de Software Solução 2: Alternância obrigatória A variável vez determina de quem é a vez de acessar a região crítica. Se vez = 0 o processo 0 acessa a região crítica. Após acessar a região, o processo 0 cede a vez para o processo 1 fazendo a variável vez = 1.
Soluções de Software Problema: Se o processo 0 termina a sua região não crítica e volta ao início do laço. A ele não será permitido entrar em sua região crítica agora, pois a variável vez está em 1 e o processo 1 está ocupado na sua região não crítica. Ele fica preso em seu processo while até que o processo 1 coloque a variável vez para 0. Conclusão: Alternar a vez não é uma boa idéia quando um processo for muito mais lento do que o outro.
Soluções de Software Solução 3: Algoritmo de Peterson Os algoritmos evoluíram e chegamos ao algoritmo de Peterson que apresenta uma solução para o problema da exclusão mútua entre dois processos e que pode ser generalizada para o caso de n processos. Nesse algoritmo, há mais uma variável “Vez” para resolver o conflito gerado pela concorrência.
void process_A(void){ while(1){ CA = 1; vez = ‘B’; while ( CB = 1 and vez = ‘B’); Regiao_critica_A; CA = 0; Regiao_nao_critica_A(); } void process_B(void){ CB = 1; Vez = ‘A’; while ( CA = 1 and vez = ‘A’); Regiao_critica_B; CB = 0; Regiao_nao_critica_B(); void main(void){ bool CA, CB; char vez; CA := 0; CB := 1; process_A(); process_B();
Soluções de Software Apesar de todas as soluções até então apresentadas, implementarem a exclusão mútua. Elas apresentam um inconveniente, conhecido como espera ocupada. Na espera ocupada, toda vez que um processo não conseguir entrar na região crítica , por já existir outro processo acessando o recurso, o processo permanece em loop, testando uma condição até que lhe seja permitido o acesso. Desta forma, o processo em looping consome tempo do processador desnecessariamente, podendo degradar o desempenho.