1 / 31

Sistemas Operacionais

Sistemas Operacionais. 3. Concorrência Texto base: capítulo 2 Modern Operating Systems A.S. Tanenbaum. O que envolve?. O conceito de concorrência envolve. compartilhamento de recursos: problema fundamental da exclusão mútua sincronização entre processos comunicação entre processos.

tanek-scott
Download Presentation

Sistemas Operacionais

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Sistemas Operacionais 3. Concorrência Texto base: capítulo 2 Modern Operating Systems A.S. Tanenbaum

  2. O que envolve? • O conceito de concorrência envolve • compartilhamento de recursos: problema fundamental da exclusão mútua • sincronização entre processos • comunicação entre processos

  3. Algumas dificuldades • Compartilhamento de recursos globais • e.g., variáveis globais: leituras e escritas • Gerenciamento da alocação de recursos • e.g., uma unidade de E/S deve ficar alocada a um processo suspenso? • Localização de erros em programas • e.g., como reproduzir situações?

  4. processo A out = 4 processo B Corrida lista do spooler daemon de impressão impressora abc 4 prog.c 5 prog.n 6 7 in = 7

  5. Compartilhando código echo () char in, out; { in = getch(); out = in; putchar(out); }

  6. Logo ... • Resultado da execução de um processo deve ser independente da velocidade de execução deste processo relativamente a outros processos concorrentes • Atenção: o problema também ocorre em multiprocessadores

  7. Concorrência: problemas • Exclusão mútua • seções críticas • Bloqueio • P1 com R1 e precisa de R2 • P2 com R2 e precisa de R1 • Esfomeação • P1, P2 e P3 querem R; suponha P1 e P2 passando o controle um para o outro

  8. Requisitos: exclusão mútua • Dois processos não podem estar simultâneamente em suas seções críticas • Nenhuma hipótese deve ser feita sobre a velocidade ou número de processadores • Nenhum processo fora de sua crítica pode bloquear outro processo • Nenhum processo deve esperar indefinidamente para entrar em sua seção crítica

  9. Espera ocupada (1) • Desabilitando interrupções • solução mais simples: desabilita antes de entrar na seção crítica; habilita antes de sair • dá muito poder a processos do usuário • não funciona quando existe mais de um processador • útil no núcleo do SO

  10. Espera ocupada (2) • Alternância estrita while (TRUE) { while (vez != 0); /*espera*/ seção_crítica(); vez = 1; seção_não_crítica(); } while (TRUE) { while (vez != 1); /*espera*/ seção_crítica(); vez = 0; seção_não_crítica(); } • Não é boa idéia quando um processo é muito mais lento que o outro (cond. 3)

  11. Solução de Peterson #define FALSE 0 #define TRUE 1 #define N 2 /* número de processos */ int turn; /* de quem é a vez? */ int interested[N]; /* inicialmente 0 (FALSE) */ void enter_region (int process) { int other; /* número do outro processo */ other = 1 - process; interested[process] = TRUE; /* indique seu interesse */ turn = process; /* set flag */ while (turn == process && interested[other] == TRUE); } void leave_region int process) { interested[process] = FALSE; /* indica saída da região crítica */ }

  12. Ainda a espera ocupada • A instrução TSL (test and set lock) • lê o conteúdo de uma palavra de memória e armazena um valor: operação indivisível • a UCP que executa TSL bloqueia o barramento de memória: nenhuma outra UCP acessa memória durante ciclo da TSL • uso de uma variável compartilhada para coordenar o acesso à memória (flag, no exemplo)

  13. Uso da TSL enter_region: tsl register, flag | register  flag e flag  1 cmp register, #0 | flag era zero? jnz enter_region | se não era zero, continue testando ret | retorna; entrou na região crítica leave_region: mov flag, #0 | flag  0 ret | retorna

  14. Inversão de prioridades? • Exemplo: • dois processos, A (alta) e B (baixa) • B na região crítica; A torna-se pronto • A inicia espera ocupada; B nunca sairá da seção crítica • A fica em espera eterna

  15. Bloqueio  espera ocupada • A espera ocupada implica em desperdício de tempo de UCP • Vejamos primitivas que bloqueiam em vez de desperdiçar tempo de UCP quando acesso à seção crítica é negado: sleep() e wakeup(p)

  16. produtor consumidor buffer [N] Produtor-consumidor (P-C) • Dois processos compartilham um buffer de tamanho fixo: um coloca informação e o outro retira  assincronismo

  17. O produtor #define N 100 int count = 0; void producer (void) { int item; while (TRUE) { produce_item (&item); if (count == N) sleep(); /* espere, se buffer cheio*/ enter_item (item); count = count + 1; if (count == 1) wakeup (consumer); /* buffer vazio? */ } }

  18. O consumidor void consumer (void) { int item; while (TRUE) { if (count == 0) sleep(); /* espere, se buffer vazio*/ remove_item (&item); count = count - 1; if (count == N-1) wakeup(producer); /* buffer cheio? */ consume_item(item); } }

  19. Acesso irrestrito a variável • Variável count: • buffer vazio, consumidor lê count=0, escalonador pára de executar consumidor e dispara produtor • produtor produz um item, incrementa count, chama wakeup(consumidor) • consumidor não estava dormindo: sinal de wakeup é perdido • consumidor é escalonado e vai dormir; produtor enche o buffer e vai dormir

  20. Semáforo • Variável especial, chamada semáforo, é usada para sinalização • Se um processo está esperando por um sinal, ele será suspenso até receber o sinal • Operações de sinal e espera: atômicas • Uso de fila para manter processos que esperam no semáforo

  21. para exclusão mútua para sincronização P-C com semáforos #define N 100 typedef int semaphore; semaphore mutex = 1; /* controla acesso à região crítica */ semaphore empty = N; /* conta lugares vazios */ semaphore full = 0; /* conta lugares cheios */ void producer (void) { int item; while (TRUE) { produce_item (&item); down (&empty); down (&mutex); /* entra região crítica */ enter_item (item); up (&mutex); /* sai da região crítica */ up (&full); } } void consumer (void) { int item; while (TRUE) { down (&full); down (&mutex); /* entra região crítica*/ remove_item (&item); up (&mutex); /* sai da região crítica*/ up (&empty); consume_item (item); } }

  22. O problema dos filósofos

  23. Uma primeira solução ... #define N 5 /* número de filósofos */ void philosopher (int i) { while (TRUE) { think(); take_fork (i); /* pega garfo à esquerda */ take_fork ((i+1)%N); /* pega garfo à direita */ eat (); put_fork (i); /* devolve garfo da esquerda */ put_fork ((i+1)%N); /* devolve garfo da direita */ } }

  24. Problemas! • Se todos pegarem o garfo da esquerda (direita) simultâneamente teremos bloqueio (deadlock) • Variação: pega o da esquerda, testa o da direita. Contudo se todos fizerem isso simultâneamente teremos esfomeação • Solução: proteger região crítica com semáforo: possível perda de paralelismo

  25. ... uma solução #define N 5 #define LEFT (i-1)%N #define RIGHT (i+1)%N #define THINKING 0 #define HUNGRY 1 #define EATING 2 typedef int semaphore; int state[N]; /* array para guardar estado de cada filósofo */ semaphore mutex = 1; /* exclusão mútua para a região crítica */ semaphore s[N]; /* um semáforo por filósofo */

  26. ... uma solução (cont.) void philosopher (int i) { while (TRUE) { think(); take_forks(i); eat(); put_forks(i); } }

  27. ... uma solução (cont.) void take_forks (int i) { down (&mutex); /* entra região crítica */ state[i] = HUNGRY; test(i); /* tenta pegar dois garfos */ up (&mutex); /* sai da região crítica */ down (&s[i]); /* bloqueia se não pegou ambos os garfos */ } test()

  28. ... uma solução (cont.) void put_forks (int i) { down (&mutex); /* entra região crítica */ state[i] = THINKING; test (LEFT); /* vizinho da esquerda pode comer? */ test (RIGHT); /* vizinho da direita pode comer? */ up (&mutex); /* sai da região crítica */ } test()

  29. ... uma solução (cont.) void test (int i) { if (state[i] == HUNGRY && state[LEFT] != EATING && state[RIGHT] != EATING) { state[i] = EATING; up (&s[i]); } } para i corrente! sinaliza que pegou ambos os garfos! take_forks() put_forks()

  30. Outras formas • Embora semáforos pareçam simples (baixo nível), problemas podem surgir se a ordem das operações down forem impróprias: uso demonitores (linguagem) • E se é necessário a troca de informações entre máquinas processos?  troca de mensagens

  31. Leitura suplementar • Operating Systems Concepts, A. Silberschatz e P.B. Galvin, Addison-Wesley • Operating Systems: Internals and Design Principles, W. Stallings, Prentice Hall

More Related