Escolar Documentos
Profissional Documentos
Cultura Documentos
de Processos
Operating System Concepts – 9th Edition 5.1 Silberschatz, Galvin and Gagne ©2013
Sobre a apresentação (About the slides)
The slides and figures in this presentation are copyright Silberschatz, Galvin
and Gagne, 2009. This presentation has been modified by Cristiano Costa
(cac@unisinos.br). Basically it was translated to Brazilian Portuguese. This
presentation has been updated to the 9th edition of the book released in 2013.
You can access the original slides at http://www.os-book.com
The 2009 version can be downloaded at http://www.inf.unisinos.br/~cac
Operating System Concepts – 9th Edition 5.2 Silberschatz, Galvin and Gagne ©2013
Módulo 5: Sincronização de Processos
! Fundamentos
! O problema da Seção Crítica
! Solução de Peterson
! Hardware de Sincronização
! Mutex Locks
! Semáforos
! Problemas Clássicos de Sincronização
! Monitores
Operating System Concepts – 9th Edition 5.3 Silberschatz, Galvin and Gagne ©2013
Objetivos
! Introduzir o problema da seção crítica, em que as soluções podem ser
usadas para garantir a consistência de dados compartilhados
Operating System Concepts – 9th Edition 5.4 Silberschatz, Galvin and Gagne ©2013
Fundamentos
! Processos podem executar concorrentemente.
" Podem ser interrompidos em qualquer instante de tempo, completando
apenas parcialmente a execução.
Operating System Concepts – 9th Edition 5.5 Silberschatz, Galvin and Gagne ©2013
Produtor
while (true) {
Operating System Concepts – 9th Edition 5.6 Silberschatz, Galvin and Gagne ©2013
Consumidor
while (true) {
while (counter == 0)
; // não faz nada
next_consumed = buffer[out];
out = (out + 1) % BUFFER_SIZE;
counter--;
/* consome o item em next_consumed
}
Operating System Concepts – 9th Edition 5.7 Silberschatz, Galvin and Gagne ©2013
Condição de Corrida
! counter++ pode ser implementado como
register1 = counter
register1 = register1 + 1
counter = register1
! counter-- pode ser implementado como
register2 = counter
register2 = register2 - 1
counter = register2
! Considere a seguinte ordem de execução com “counter = 5” inicialmente:
S0: producer execute register1 = counter {register1 = 5}
S1: producer execute register1 = register1 + 1 {register1 = 6}
S2: consumer execute register2 = counter {register2 = 5}
S3: consumer execute register2 = register2 - 1 {register2 = 4}
S4: producer execute counter = register1 {counter = 6 }
S5: consumer execute counter = register2 {counter = 4}
Operating System Concepts – 9th Edition 5.8 Silberschatz, Galvin and Gagne ©2013
Problema da Seção Crítica
! Considere um sistema com n processos {p0, p1, … pn-1}
! Cada um dos n processos possui um segmento de código que
é uma seção crítica
" O processo pode mudar variável, atualizar uma tabela,
escrever em arquivo, etc
" Quando um processo está na seção crítica, nenhum outro
pode estar na sua seção crítica
! O problema da seção crítica é projetar um protocolo para
resolver essa situação
! Cada processo deve pedir permissão para entrar na seção
crítica (na seção de entrada), seguir a seção crítica com uma
seção de saída, então executar a seção restante.
Operating System Concepts – 9th Edition 5.9 Silberschatz, Galvin and Gagne ©2013
Solução para o Problema da Seção Crítica
Operating System Concepts – 9th Edition 5.10 Silberschatz, Galvin and Gagne ©2013
Solução para o Problema da Seção Crítica
Operating System Concepts – 9th Edition 5.11 Silberschatz, Galvin and Gagne ©2013
Seção Crítica
Operating System Concepts – 9th Edition 5.12 Silberschatz, Galvin and Gagne ©2013
Desabilitação de Interrupção
! Em sistemas com um único processador, a solução mais simples é fazer
com que cada processo desabilite interrupções no início da seção crítica e
as reabilite antes de deixar sua seção crítica.
! Com interrupções desabilitadas, interrupções do temporizador não podem
ocorrer e não há troca de processos.
! Esta abordagem é problemática porque processos de usuário podem não
habilitar as interrupções novamente. Além disso, ela não funciona em
sistemas com múltiplos processadores.
! É uma solução conveniente para o kernel em sistemas com um único
processador.
Operating System Concepts – 9th Edition 5.13 Silberschatz, Galvin and Gagne ©2013
Tentativas de Solução
para o Problema da Seção Crítica
! Inicialmente serão consideradas soluções para dois processos apenas.
Operating System Concepts – 9th Edition 5.14 Silberschatz, Galvin and Gagne ©2013
Tentativa 1 – Com Espera Ocupada
(Busy Waiting)
! Variáveis compartilhadas:
" var turn: (0..1);
inicialmente turn = 0
" turn = i Þ Pi pode entrar na sua seção crítica. j = 1 - i
! Processo Pi
do {
while turn != i
; /* não faz nada */
// SEÇÃO CRÍTICA
turn = j;
// SEÇÃO RESTANTE
} while (TRUE);
! Satisfaz exclusão mútua, mas não progresso.
Operating System Concepts – 9th Edition 5.15 Silberschatz, Galvin and Gagne ©2013
Tentativa 2 – Com Espera Ocupada
(Busy Waiting)
! Variáveis compartilhadas:
" var flag: array [0..1] of boolean;
inicialmente flag [0] = flag [1] = false.
" flag [i] = true Þ Pi pronto para entrar na seção crítica. j = 1 - i
! Processo Pi
do {
flag[i] = true;
while flag[j]
; /* não faz nada */
// SEÇÃO CRÍTICA
flag [i] = false;
// SEÇÃO RESTANTE
} while (TRUE);
! Satisfaz exclusão mútua, mas não progresso.
Operating System Concepts – 9th Edition 5.16 Silberschatz, Galvin and Gagne ©2013
Solução de Peterson
! Os dois processos compartilham duas variáveis:
" int turn;
" Boolean flag[2]
Operating System Concepts – 9th Edition 5.17 Silberschatz, Galvin and Gagne ©2013
Algoritmo Para Processo Pi
do {
flag[i] = TRUE;
turn = j;
while ( flag[j] && turn == j)
; /* não faz nada */
// SEÇÃO CRÍTICA
flag[i] = FALSE;
// SEÇÃO RESTANTE
} while (TRUE);
Operating System Concepts – 9th Edition 5.18 Silberschatz, Galvin and Gagne ©2013
Sincronização por Hardware
! Muitos sistemas fornecem suporte de hardware para código de
seção crítica
! Todas as soluções a seguir são baseadas na ideia de locking
" Protege seções críticas via locks
! Sistemas Monoprocessados – podem desabilitar interrupções
" Código em execução pode executar sem preempção
" Geralmente muito ineficiente em sistemas multiprocessados
4Sistemas Operacionais que usam isso não escalam
! Arquiteturas modernas fornecem instruções atômicas especiais
de hardware
4Atômica = não interrompível
" Testar uma posição de memória e setar um valor
" Ou trocar conteúdos de duas posições na memória
Operating System Concepts – 9th Edition 5.19 Silberschatz, Galvin and Gagne ©2013
Solução para o Problema da Seção Crítica
usando Locks
do {
adquire lock
seção crítica
libera lock
seção restante
} while (TRUE);
Operating System Concepts – 9th Edition 5.20 Silberschatz, Galvin and Gagne ©2013
Instrução test_and_set
! Definição:
Operating System Concepts – 9th Edition 5.21 Silberschatz, Galvin and Gagne ©2013
Solução usando test_and_set
while (true) {
while ( test_and_set (&lock ))
; /* não faz nada */
// SECÃO CRÍTICA
lock = FALSE;
// SEÇÃO RESTANTE
}
Operating System Concepts – 9th Edition 5.22 Silberschatz, Galvin and Gagne ©2013
Instrução compare_and_swap
! Definição:
void compare_and_swap (int *value, int expected, int new_value)
{
int temp = *value;
if (*value == expected)
*value = new_value;
return temp:
}
Operating System Concepts – 9th Edition 5.23 Silberschatz, Galvin and Gagne ©2013
Solução usando compare_and_swap
! Variável booleana compartilhada lock, inicializada em FALSE; Cada
processo tem uma variável booleana key local.
! Solução:
do {
while (compare_and_swap(&lock, FALSE, TRUE) != FALSE)
; // Não faz nada
// SEÇÃO CRÍTICA
lock = FALSE;
// SEÇÃO RESTANTE
} while (TRUE)
Operating System Concepts – 9th Edition 5.24 Silberschatz, Galvin and Gagne ©2013
Exclusão Mútua com Espera Limitada
usando test_and_set()
do {
waiting[i] = TRUE;
key = 1;
while (waiting[i] && key == 1)
key = test_and_set(&lock); // or compare_and_swap(&lock, 0, 1);
waiting[i] = FALSE;
// critical section
j = (i + 1) % n;
while ((j != i) && !waiting[j])
j = (j + 1) % n;
if (j == i)
lock = FALSE;
else
waiting[j] = FALSE;
// remainder section
} while (TRUE);
Operating System Concepts – 9th Edition 5.25 Silberschatz, Galvin and Gagne ©2013
Mutex Locks
! As soluções anteriores são complicadas e geralmente inacessíveis aos
programadores de aplicação
Operating System Concepts – 9th Edition 5.26 Silberschatz, Galvin and Gagne ©2013
acquire() e release()
acquire() {
while (!available)
; /* busy wait */
available = false;;
}
release() {
available = true;
}
do {
acquire lock
critical section
release lock
remainder section
} while (true);
Operating System Concepts – 9th Edition 5.27 Silberschatz, Galvin and Gagne ©2013
Semáforo
! Ferramenta de sincronização que não requer espera ocupada (busy waiting)
! Semáforo S – variável inteira
! Duas operações padrão modificam S: wait() e signal()
" Originalmente chamadas P() e V()
! Menos Complicada
! Somente pode ser acessada via duas operações indivisíveis (atômicas)
" wait (S) {
while S <= 0
; // não faz nada
S--;
}
" signal (S) {
S++;
}
Operating System Concepts – 9th Edition 5.28 Silberschatz, Galvin and Gagne ©2013
Semáforo como uma Ferramenta Geral de Sincronização
Operating System Concepts – 9th Edition 5.29 Silberschatz, Galvin and Gagne ©2013
Implementação de Semáforo
Operating System Concepts – 9th Edition 5.30 Silberschatz, Galvin and Gagne ©2013
Implementação de Semáforo sem Espera Ocupada
typedef struct{
int value;
struct process *list;
} semaphore;
Operating System Concepts – 9th Edition 5.31 Silberschatz, Galvin and Gagne ©2013
Implementação de Semáforo sem Espera Ocupada (Cont.)
! Implementação de wait:
wait(semaphore *S) {
S->value--;
if (S->value < 0) {
adiciona esse processo em S->list;
block();
}
}
! Implementação de signal:
signal(semaphore *S) {
S->value++;
if (S->value <= 0) {
remove o processo P de S->list;
wakeup(P);
}
}
Operating System Concepts – 9th Edition 5.32 Silberschatz, Galvin and Gagne ©2013
Deadlock (Impasse) e Starvation (Abandono)
Operating System Concepts – 9th Edition 5.33 Silberschatz, Galvin and Gagne ©2013
Inversão de Prioridade
! Priority Inversion – inversão de prioridade. Problema de escalonamento em
que um processo de baixa prioridade mantém um lock necessário para
um processo de maior prioridade
" Considere processos L < M < H e que o processo H precisa de um
semáforo que está com L.
" Suponha agora que M fique pronto e colocado em execução,
preemptando L. Indiretamente, M (menor prioridade) está afetando o
tempo que H (maior prioridade) fica esperando.
" Este problema pode ser resolvido pelo protocolo de herança de
prioridade (priority-inheritance protocol) em que um processo que está
acessando um semáforo herda a prioridade de outro processo de maior
prioridade quando.
Operating System Concepts – 9th Edition 5.34 Silberschatz, Galvin and Gagne ©2013
Problemas com Semáforos
Operating System Concepts – 9th Edition 5.35 Silberschatz, Galvin and Gagne ©2013
Monitores
! Abstração de alto nível que fornece um mecanismo conveniente e
eficiente para sincronização de processos
! Tipo abstrato de dados (ADT). Variáveis internas são acessíveis
apenas pelo código dentro do procedimento.
! Somente um processo por vez pode estar ativo dentro do monitor
monitor nome-monitor
{
// declaração de variáveis compartilhadas
procedure P1 (…) { …. }
…
Operating System Concepts – 9th Edition 5.36 Silberschatz, Galvin and Gagne ©2013
Visão Esquemática de um Monitor
Operating System Concepts – 9th Edition 5.37 Silberschatz, Galvin and Gagne ©2013
Variáveis Condicionais
! condition x, y;
Operating System Concepts – 9th Edition 5.38 Silberschatz, Galvin and Gagne ©2013
Monitor com Variáveis Condicionais
Operating System Concepts – 9th Edition 5.39 Silberschatz, Galvin and Gagne ©2013
Pthreads
Operating System Concepts – 9th Edition 5.40 Silberschatz, Galvin and Gagne ©2013
Pthreads
Operating System Concepts – 9th Edition 5.41 Silberschatz, Galvin and Gagne ©2013
Variáveis Condicionais
Operating System Concepts – 9th Edition 5.42 Silberschatz, Galvin and Gagne ©2013
pthread cond signal(&condp);
pthread mutex unlock(&the mutex)
}
138
Variáveis Condicionais
PROCESSES AND THREADS CHAP. 2
}
pthread exit(0);
#include <stdio.h>
#include <pthread.h> int main(int argc, char **argv)
{
#define MAX 1000000000 /* how many numbers to produce */
pthread t pro, con;
pthread mutex t the mutex;
pthread cond t condc, condp; /* used for signaling */ pthread mutex init(&the mutex, 0);
int buffer = 0; /* buffer used between producer and consumer */ pthread cond init(&condc, 0);
pthread cond init(&condp, 0);
void *producer(void *ptr) /* produce data */
{ int i; pthread create(&con, 0, consumer, 0);
pthread create(&pro, 0, producer, 0);
for (i= 1; i <= MAX; i++) { pthread join(pro, 0);
pthread mutex lock(&the mutex); /* get exclusive access to buffer */
while (buffer != 0) pthread cond wait(&condp, &the mutex);
pthread join(con, 0);
buffer = i; /* put item in buffer */ pthread cond destroy(&condc);
pthread cond signal(&condc); /* wake up consumer */ pthread cond destroy(&condp);
pthread mutex unlock(&the mutex); /* release access to buffer */ pthread mutex destroy(&the mutex);
} }
pthread exit(0);
}
void *consumer(void *ptr) /* consume data */ Figure 2-32. Using threads to solve the pr
{ int i;
for (i = 1; i <= MAX; i++) {
pthread mutex lock(&the mutex); /* get exclusive access to buffer */
while (buffer ==0 ) pthread cond wait(&condc, &the mutex);
buffer = 0; /* take item out of buffer */
pthread cond signal(&condp); /* wake up producer */
pthread mutex unlock(&the mutex); /* release access to buffer */
}
pthread exit(0);
}
Operating System Concepts – 9th Edition 5.51 Silberschatz, Galvin and Gagne ©2013
Problema do Buffer de Tamanho Limitado
Operating System Concepts – 9th Edition 5.52 Silberschatz, Galvin and Gagne ©2013
Problema do Buffer de Tamanho Limitado (Cont.)
do {
// produz um item
wait (empty);
wait (mutex);
signal (mutex);
signal (full);
} while (TRUE)
Operating System Concepts – 9th Edition 5.53 Silberschatz, Galvin and Gagne ©2013
Problema do Buffer de Tamanho Limitado (Cont.)
do {
wait (full);
wait (mutex);
signal (mutex);
signal (empty);
} while (TRUE);
Operating System Concepts – 9th Edition 5.54 Silberschatz, Galvin and Gagne ©2013
Problema dos Leitores e Escritores
! Dados Compartilhados
" Conjunto de dados
" Semáforo rw_mutex inicializado em 1.
" Semáforo mutex inicializado em 1.
" Inteiro read_count inicializado em 0.
Operating System Concepts – 9th Edition 5.55 Silberschatz, Galvin and Gagne ©2013
Problema dos Leitores e Escritores (Cont.)
do {
wait (rw_mutex) ;
// writing is performed
signal (rw_mutex) ;
} while (TRUE);
Operating System Concepts – 9th Edition 5.56 Silberschatz, Galvin and Gagne ©2013
Problema dos Leitores e Escritores (Cont.)
! A estrutura de um processo leitor
do {
wait (mutex) ;
read_count ++ ;
if (read_count == 1)
wait (rw_mutex) ;
signal (mutex)
// reading is performed
wait (mutex) ;
readcount - - ;
if (read_count == 0)
signal (rw_mutex) ;
signal (mutex) ;
} while (TRUE);
Operating System Concepts – 9th Edition 5.57 Silberschatz, Galvin and Gagne ©2013
Problema do Jantar dos Filósofos
Operating System Concepts – 9th Edition 5.58 Silberschatz, Galvin and Gagne ©2013
Problema do Jantar dos Filósofos (Cont.)
! A estrutura do Filósofo i:
do {
wait ( chopstick[i] );
wait ( chopStick[ (i + 1) % 5] );
// comer
signal ( chopstick[i] );
signal (chopstick[ (i + 1) % 5] );
// pensar
} while (TRUE);
Operating System Concepts – 9th Edition 5.59 Silberschatz, Galvin and Gagne ©2013
Solução para o problema dos Filósofos
monitor DP
{
enum { THINKING; HUNGRY, EATING) state [5] ;
condition self [5];
Operating System Concepts – 9th Edition 5.60 Silberschatz, Galvin and Gagne ©2013
Solução para o problema dos Filósofos (Cont.)
initialization_code() {
for (int i = 0; i < 5; i++)
state[i] = THINKING;
}
}
Operating System Concepts – 9th Edition 5.61 Silberschatz, Galvin and Gagne ©2013
Solução para o problema dos Filósofos (Cont.)
dp.pickup (i)
COMER
dp.putdown (i)
Operating System Concepts – 9th Edition 5.62 Silberschatz, Galvin and Gagne ©2013
Fim do Capítulo 5
Operating System Concepts – 9th Edition 5.72 Silberschatz, Galvin and Gagne ©2013