Você está na página 1de 6

Produtor - Consumidor c/ Buffer Circular (1)

Sincronizao de Processos (4)

Dois problemas p/ resolver:


- Variveis compartilhada
- Coordenao quando o buffer
estiver CHEIO ou VAZIO
Prxima
insero
Buffer

Aula 13 - Exerccios - Semforos

dado4

dado1
dado3

Profa. Patrcia D. Costa LPRM/DI/UFES

Buffer com

capacidade N (vetor de N elementos).

 Variveis proxima_insercao e proxima_remocao indicam onde deve ser


feita a prxima insero e remoo no buffer.

 Efeito de buffer circular obtido atravs da forma como essas variveis


so incrementadas. Aps o valor N-1 elas voltam a apontar para a
entrada zero do vetor


% representa a operao resto da diviso

 Trs semforos, duas funes diferentes: excluso mtua e


sincronizao.


mutex: garante a excluso mtua. Deve ser iniciado com 1.


espera_dado: bloqueia o consumidor se o buffer estiver vazio. Iniciado com

espera_vaga: bloqueia produtor se o buffer estiver cheio. Iniciado com N.

0.

Profa. Patrcia D. Costa LPRM/DI/UFES

struct tipo_dado buffer[N];


int proxima_insercao = 0;
int proxima_remocao = 0;
...
semaphore mutex = 1;
semaphore espera_vaga = N;
semaphore espera_dado = 0;

Produtor Consumidor c/ Buffer Circular (2)




dado2

Sistemas Operacionais 2008/1

Prxima
remoo

Sistemas Operacionais 2008/1

Produtor Consumidor c/
Buffer Circular (3)

-----------------------------------------void produtor(void){
...
down(espera_vaga);
down(mutex);
buffer[proxima_insercao] = dado_produzido;
proxima_insercao = (proxima_insercao + 1) % N;
up(mutex);
up(espera_dado);
... }
-----------------------------------------void consumidor(void){
...
down(espera_dado);
down(mutex);
dado_a_consumir := buffer[proxima_remocao];
proxima_remocao := (proxima_remocao + 1) % N;
up(mutex);
up(espera_vaga);
... }

Profa. Patrcia D. Costa LPRM/DI/UFES

Sistemas Operacionais 2008/1

Problemas Clssicos:
OS Filsofos Glutes
Dados Compartilhados

Problemas Clssicos:
OS Filsofos Glutes

typedef int semaphore;


semaphore forks[N];

void philosopher(int i)
{ while (TRUE) {
think();
down(forks[i]);
down(forks[i+1])
eat();
up(forks[i]);
up(forks[i+1]);
}
}

Soluo simples (garante que dois vizinhos comam


simultaneamente) ... mas ela pode causar deadlock!!!
Para resolver isso, uma soluo seria permitir que um
filsofo pegue seus garfos somente se ambos
estiverem livres (neste caso isso deve ser feito dentro
de uma regio crtica... )
Profa. Patrcia D. Costa LPRM/DI/UFES

Sistemas Operacionais 2008/1

Profa. Patrcia D. Costa LPRM/DI/UFES

Problemas Clssicos:
OS Filsofos Glutes
Dados Compartilhados
#define N 5
#define LEFT (i+N-1)%N
#define RIGHT (i+1)%N
#define THINKING 0
#define HUNGRY 1
#define EATING 2
int state[N];
typedef int semaphore;
semaphore mutex = 1;
semaphore s[N];

Profa. Patrcia D. Costa LPRM/DI/UFES

void philosopher(int i)
{ while (TRUE) {
think();
take_forks(i);
eat();
put_forks(i); }}
void take_forks(int i)
/* acquire two forks
{ down(&mutex);
or block =
*/ HUNGRY;
state[i]
test(i);
up(&mutex);
down(&s[i]); }

void put_forks(i)
put both forks
{ /*
down(&mutex);
back on =
table
*/
state[i]
THINKING;
test(LEFT);
test(RIGHT);
up(&mutex); }

void test(i)
{ if (state[i] == HUNGRY &&
state[LEFT] != EATING &&
state[RIGHT] != EATING) {
}
}
state[i] = EATING;
up(&s[i]);
}
7
}
Sistemas Operacionais 2008/1

Soluo para
OS Filsofos
Glutes

Sistemas Operacionais 2008/1

#define N 5
#define LEFT (i+N-1)%N
#define RIGHT (i+1)%N
#define THINKING 0
#define HUNGRY 1
#define EATING 2
typedef int semaphore;
int state[N];
semaphore mutex = 1;
semaphore s[N];

/* number of philosophers */
/* number of is left neighbor */
/* number of is right neighbor */
/* philosopher is thinking */
/* philosopher is trying to get forks */
/* philosopher is eating */
/* semaphores are a special kind of int */
/* array to keep track of everyones state */
/* mutual exclusion for critical regions */
/* one semaphore per philosopher */

void philosopher(int i)
{ while (TRUE) {
think();
take_forks(i);
eat();
put_forks(i); }}

/* i: philosopher number, from 0 to N-1 */


/* repeat forever */
/* philosopher is thinking */
/* acquire two forks or block */
/* yum-yum, spaghetti */
/* put both forks back on table */

void take_forks(int i)
{ down(&mutex);
state[i] = HUNGRY;
test(i);
up(&mutex);
down(&s[i]); }

/* i: philosopher number, from 0 to N-1 */


/* enter critical region */
/* record fact that philosopher i is hungry */
/* try to acquire 2 forks */
/* exit critical region */
/* block if forks were not acquired */

void put_forks(i)
{down(&mutex);
state[i] = THINKING;
test(LEFT);
test(RIGHT);
up(&mutex); }

/* i: philosopher number, from 0 to N-1 */


/* enter critical region */
/* philosopher has finished eating */
/* see if left neighbor can now eat */
/* see if right neighbor can now eat */
/* exit critical region */

void test(i)
/* i: philosopher number, from 0 to N-1 */
{ if (state[i] == HUNGRY && state[LEFT] != EATING && state[RIGHT] != EATING) {
state[i] = EATING; up(&s[i]); }}

Profa. Patrcia D. Costa LPRM/DI/UFES

Sistemas Operacionais 2008/1

Problemas Clssicos: Leitores e Escritores




Problemas Clssicos: Leitores e Escritores

Problema:
 Suponha que existe um conjunto de processos que compartilham

um determinado conjunto de dados (ex: um banco de dados).


 Existem processos que lem os dados (mas no os apagam!)
 Existem processos que escrevem os dados

Anlise do problema
 Se dois ou mais leitores acessarem os dados simultaneamente no

h problemas
 E se um escritor escrever sobre os dados?
 Podem outros processos estarem acessando simultaneamente os

mesmos dados?

Profa. Patrcia D. Costa LPRM/DI/UFES

Sistemas Operacionais 2008/1

Leitores e Escritores: Soluo possvel

Profa. Patrcia D. Costa LPRM/DI/UFES

10

Sistemas Operacionais 2008/1

Problemas Clssicos:
Leitores e Escritores
(1)

 Os escritores podem apenas ter acesso exclusivo aos dados


compartilhados
 Os leitores podem ter acesso aos dados compartilhados
simultaneamente

Escritor
while (TRUE)
int rc
down(db);
...
//protege o acesso varivel rc
//writing is
Semaphore mutex
//performed
...
//Indica a um escritor se este
up(db);
//pode ter acesso aos dados
...
Semaphore db
//nmero de leitores ativos

//Incializao:

mutex=1,
db=1,
rc=0
Profa. Patrcia D. Costa LPRM/DI/UFES

11

Leitor
while (TRUE)
down(mutex);
rc++;
if (rc == 1)
down(db);
up(mutex);
...
//reading is
//performed
...
down(mutex);
rc--;
if (rc == 0)
up(db);
up(mutex);

Sistemas Operacionais 2008/1

Profa. Patrcia D. Costa LPRM/DI/UFES

12

Sistemas Operacionais 2008/1

rcount
wcount

Leitores e Escritores: Soluo possvel





(2)

A soluo proposta simples mas pode levar starvation


do escritor
Exerccio
 Desenvolver uma soluo que atenda os processos pela ordem de

chegada, mas dando prioridade aos escritores


 Dica: quando existir um escritor pronto para escrever, este tem

prioridade sobre todos os outros leitores que cheguem aps ele


querendo ler os dados

//Nmero de leitores
//Nmero de escritores, apenas um escritor de cada vez pode ter acesso aos
//dados compartilhados
mutex_rcount
// Protege o acesso varivel rc
mutex_wcount
//Protege o acesso varivel wc
mutex
//Impede que + do que 1 leitor tente entrar na regio crtica
w_db
//Indica a um escritor se este pode ter acesso aos dados
r_db
//Permite que um processo leitor tente entrar na sua regio crtica

Inicializao
rcount = 0
wcount = 0
//semforos
mutex_rcount = 1
mutex_wcount = 1
mutex = 1
w_db = 1
r_db = 1

rcount
wcount

//Nmero de leitores
//Nmero de escritores, apenas um escritor de cada vez pode ter acesso aos
//dados compartilhados
mutex_rcount
// Protege o acesso varivel rcount
mutex_wcount
//Protege o acesso varivel wcount
mutex
//Impede que + do que 1 leitor tente entrar na regio crtica
w_db
//Indica a um escritor se este pode ter acesso aos dados
r_db
//Permite que um processo leitor tente entrar na sua regio crtica

Profa. Patrcia D. Costa LPRM/DI/UFES

13

Sistemas Operacionais 2008/1

Problema do Pombo correio


 Considere a seguinte situao.









Um pombo correio leva mensagens entre os sites A e B, mas s quando o nmero de


mensagens acumuladas chega a 20.
Inicialmente, o pombo fica em A, esperando que existam 20 mensagens para
carregar, e dormindo enquanto no houver.
Quando as mensagens chegam a 20, o pombo deve levar exatamente (nenhuma a
mais nem a menos) 20 mensagens de A para B, e em seguida voltar para A.
Caso existam outras 20 mensagens, ele parte imediatamente; caso contrrio, ele
dorme de novo at que existam as 20 mensagens.
As mensagens so escritas em um post-it pelos usurios; cada usurio, quando tem
uma mensagem pronta, cola sua mensagem na mochila do pombo. Caso o pombo
tenha partido, ele deve esperar o seu retorno p/ colar a mensagem na mochila.
O vigsimo usurio deve acordar o pombo caso ele esteja dormindo.
Cada usurio tem seu bloquinho inesgotvel de post-it e continuamente prepara uma
mensagem e a leva ao pombo.

 Usando semforos, modele o processo pombo e o processo usurio,


lembrando que existem muitos usurios e apenas um pombo.
Identifique regies crticas e no crticas na vida do usurio e do
pombo.
Profa. Patrcia D. Costa LPRM/DI/UFES

15

Sistemas Operacionais 2008/1

Escritor
while (TRUE){
down(mutex_wcount);
wcount++;
if (wcount == 1)
down(r_db);
up(mutex_wcount);
down(w_db)

//Escrita

up(w_db)
down(mutex_wcount);
wcount--;
if (wcount == 0)
up(r_db);
up(mutex_wcount);
}

Profa. Patrcia D. Costa LPRM/DI/UFES

14

Leitor
while (TRUE){
down(mutex);
down(r_db);
down(mutex_rcount);
rcount++;
if (rcount == 1)
down(w_db);
up(mutex_rcount);
up(r_db);
up(mutex);

//Leitura dos dados

down(mutex_rcount);
rcount--;
if (rcount == 0)
up(w_db);
up(mutex_rcount);
) 2008/1
Sistemas Operacionais

Problema do Pombo correio: Soluo

#define N 20

int contaPostIt=0;
semaforo mutex=1; //controlar acesso varivel contaPostIt
semaforo cheia=0; //usado para fazer o pombo dormir enquanto h 20 msg
semaforo enchendo=N; //Usado p/ fazer usurios dormirem enquanto pombo
//est fazendo o transporte

usuario() {
while(true){
down(enchendo);
down(mutex);
colaPostIt_na_mochila();
contaPostIt++;
if (contaPostIt==N)
up(cheia);
up(mutex);
}
}
Profa. Patrcia D. Costa LPRM/DI/UFES

pombo() {
while(true){
down(cheia);
down(mutex);
leva_mochila_ate_B_e_volta();
contaPostIt=0;
for(i=0;i<N;i++)
up(enchendo);
up(mutex);
}
}
16

Sistemas Operacionais 2008/1

Problemas Clssicos: O Barbeiro Dorminhoco

#define CHAIRS 5
typedef int semaphore;
semaphore customers = 0;
semaphore barbers = 0;
semaphore mutex = 1;
int waiting = 0;
void barber(void) {
while (TRUE)
{ down(customers);
down(mutex);
waiting = waiting - 1;
up(barbers);
up(mutex);
cut_hair();
}}

Profa. Patrcia D. Costa LPRM/DI/UFES

Exerccio
 Considere

17

Sistemas Operacionais 2008/1

o seguinte grafo de precedncia

S1 -------> S2 -----> S5----------> S7


| \
/
^
| \
/
|
v
------> S3 -->
|
\
\
/
\
\
/
-------> S4 ->---> S6---

que ser executado por trs processos, conforme cdigo abaixo:


cobegin
P1: begin S1; S3; end;
P2: begin S2; S5; S7; end;
P3: begin S4; S6; end;
coend
Adicione semforos a este programa, e as respectivas chamadas s suas
operaes, de modo que a precedncia definida acima seja alcanada.
Profa. Patrcia D. Costa LPRM/DI/UFES

19

Sistemas Operacionais 2008/1

void customer(void) {
down(mutex);
if (waiting < CHAIRS) {
waiting = waiting + 1;
up(customers);
up(mutex);
down(barbers);
get_haircut(); }
else {
up(mutex); }}

Profa. Patrcia D. Costa LPRM/DI/UFES

/* # chairs for waiting customers */


/* use your imagination */
/* # of customers waiting for service */
/* # of barbers waiting for customers */
/* for mutual exclusion */
/* customers are waiting (not being cut) */

/* go to sleep if # of customers is 0 */
/* acquire access to waiting */
/* decrement count of waiting customers */
/* one barber is now ready to cut hair */
/* release waiting */
/* cut hair (outside critical region) */

/* enter critical region */


/* if there are no free chairs, leave */
/* increment count of waiting customers */
/* wake up barber if necessary */
/* release access to waiting */
/* go to sleep if # of free barbers is 0 */
/* be seated and be serviced */
/* shop is full; do not wait */
18

Sistemas Operacionais 2008/1

Exerccio (2)

Um semforo mltiplo estende semforos de maneira a
permitir que as primitivas up e down operem em vrios
semforos simultaneamente. Isto til para requisitar e
liberar vrios recursos atravs de uma operao atmica.
Como voc implementaria tais primitivas usando os
semforos estudados no curso? (Observe que voc, como
implementador da primitiva, pode acessar o valor do
contador associado ao semforo diretamente. Ou seja,
voc tem disponvel na hora de implementar Down (R1,
R2, ..., Rn) ou Up (R1, R2, ..., Rn) uma rotina
valor_do_contador (R)'', que devolve o valor do contador
associado a um semforo).
Profa. Patrcia D. Costa LPRM/DI/UFES

20

Sistemas Operacionais 2008/1

Resposta

Resposta

Down (R1, R2, ... , Rn) {


while (1){
down(mutex1); //garante excluso mtua
if ((valor_do_contador(R1)>0) &&
(valor_do_contador(R2)>0) && ...
(valor_do_contador(Rn)>0))
break; //sai do loop
down(mutex2); //garante atomicidade dos multiplos downs
up(mutex1);
else {
up(mutex1);//Libera o semforo
sleep(m);// e adormece por um tempo m p/ tentar fazer um down mais tarde
}
}
down(R1);
down(R2);
...
down(Rn);
up(mutex2);
}

Profa. Patrcia D. Costa LPRM/DI/UFES

21

Sistemas Operacionais 2008/1

Up (R1, R2, ... , Rn) {


down(mutex);
up(R1);
up(R2);
...
up(Rn);
up(mutex);
}

Profa. Patrcia D. Costa LPRM/DI/UFES

22

Sistemas Operacionais 2008/1

Você também pode gostar