• Nenhum resultado encontrado

Programação de Sistemas

N/A
N/A
Protected

Academic year: 2021

Share "Programação de Sistemas"

Copied!
7
0
0

Texto

(1)

Programação de Sistemas

Programação de Sistemas

Jantar dos filósofos : 1/14

Jantar dos filósofos

Introdução (1)

• O jantar dos filósofos, proposto por Dijkstra em 1971, é o

problema mais famoso de acesso a recursos partilhados

por processos concorrentes.

Cinco filósofos estão sentados numa mesa

redonda, alternam entre pensar e comer.

O alimento consumido é esparguete,

disponibilizado em quantidades ilimitadas.

Para comer esparguete necessitam de dois

garfos, colocados ao seu lado.

Impasse ocorre se todos os filósofos

pegarem o garfo do mesmo lado (ex:

direito), ficando à espera que o seu colega

(2)

Introdução (2)

• Os filósofos e os garfos são numerados 0..N-1 (N é o

número de filósofos).

• O programa recebe o tempo de simulação na linha de

comando.

Programação de Sistemas

Jantar dos filósofos : 3/14

comando.

• Tempos de espera usam função

sleep(unsigned sec);

/* refeição demora entre 2+0 e 2+2 segundos */

#define eat(i) {printf("Phil %d eating\n",i);sleep(2+(int)(random())%3;} #define think(i) {printf("Phil %d thinking\n",i); sleep(6+(int)(random())%6;}

Introdução (3)

• Exploradas duas estratégias de sincronização dos recursos

escassos (garfos)

1.

Estado de cada filósofo conhecido por todos

Semáforo door assegura exclusão mútua.

Caso pelo menos um dos vizinhos esteja a comer, o filósofo fica

bloqueado na tabela de semáforos s (é libertado pelo filósofo

bloqueado na tabela de semáforos s (é libertado pelo filósofo

vizinho, quando retorna garfo).

2.

Garfos geridos por gestor, através de mensagens enviadas por

pipes.

A solução por gestor é mais pesada (mais processos e

custo de distribuição de mensagens), mas

(3)

Resolução por semáforos (1)

• Os estados de cada filósofo indicados numa tabela

typedef enum {thinking, hungry, eating} Tstate;

Tstate state[N];

• Os vizinhos do filósofo i são

– Esquerdo: (i-1)%N

Programação de Sistemas

Jantar dos filósofos : 5/14

– Esquerdo: (i-1)%N

– Direito: (i+1)%N

• O fio de execução do filósofo possui como parâmetro a

sua posição.

• Ao todo existem 6 semáforos

– Acesso à região crítica: sem_t door;

– Espera que vizinho liberte garfo: sem_t s[N];

Resolução por semáforos (2)

#include <pthread.h> #include <semaphore.h> #include <stdlib.h> #include <stdio.h> #include <unistd.h> #define N 5 // philosophers

#define left(i) ( (i-1)%N ) #define right(i) ( (i+1)%N )

#define eat(i) {printf("Phil %d eating\n",i); sleep(2+2*random()/RAND_MAX);} #define eat(i) {printf("Phil %d eating\n",i); sleep(2+2*random()/RAND_MAX);} #define think(i) {printf("Phil %d thinking\n",i);sleep(6+3*random()/RAND_MAX);}

typedef struct {

int pos; } arguments;

typedef enum {thinking, hungry, eating} Tstate;

Tstate state[N];

sem_t door; /* acesso à regiao crítica */ sem_t s[N]; /* espera de cada filósofo */

(4)

Resolução por semáforos (3)

void take_forks(int i) {

sem_wait(&door);

state[i] = hungry;

test(i);

sem_post(&door);

sem_wait(&s[i]); /* bloqueia se grafos não foram adquiridos */

}

Programação de Sistemas

Jantar dos filósofos : 7/14

void put_forks(int i) {

sem_wait(&door);

state[i] = thinking;

test(left(i));

test(right(i));

sem_post(&door);

}

Resolução por semáforos (4)

void test(int i) {

if ( state[i] == hungry ) {

if( state[left(i)]!= eating && state[right(i)]!= eating ){

state[i] = eating;

sem_post(&s[i]); }

else printf("Phil %d hungry\n", i);

}

}

}

void *philosopher(void *arg) {

arguments *argument=(arguments *)arg;

int i;

i = argument->pos;

while(1) {

think(i)

take_forks(i);

eat(i)

put_forks(i); }

}

(5)

Resolução por semáforos (5)

int main(int argc, char *argv[]) { int i;

pthread_t t[N]; arguments *arg;

if(argc!=2) {

fprintf( stderr,“%s time\n“,argv[0] ); exit(1); }

/* inicializa semáforos */

for(i=0; i<N;i++) sem_init( &s[i],0,0 );

[rgc@asterix JantarFilosofos]$ JF1 17 Phil 0 thinking Phil 1 thinking Phil 2 thinking Phil 3 thinking Phil 4 thinking Phil 0 eating Phil 1 hungry Phil 2 eating Phil 3 hungry Phil 4 hungry Phil 1 hungry Phil 0 thinking

Programação de Sistemas

Jantar dos filósofos : 9/14

for(i=0; i<N;i++) sem_init( &s[i],0,0 ); sem_init( &door,0,1 );

for(i=0;i<N;i++) state[i]=thinking; for(i=0;i<N;i++) {

arg = (arguments *)malloc(sizeof(arguments)); arg->pos=i;

t[i]=pthread_create(&(t[i]),NULL,philosopher,(void *)arg); if(t[i]!=0) {

fprintf( stderr,"Erro na criacao do thread\n“ ); exit(1); } } sleep( atoi(argv[1]) ); return 0; } Phil 0 thinking Phil 2 thinking Phil 1 eating Phil 3 eating Phil 1 thinking Phil 3 thinking Phil 4 eating Phil 4 thinking Phil 0 eating Phil 2 eating Phil 0 thinking Phil 2 thinking Phil 1 eating Phil 3 eating [rgc@asterix JantarFilosofos]$

Resolução por mensagens (1)

• Garfos vizinhos do filósofo i são i e (i+1)%N

• O simulador possui os seguintes canais de comunicação

– Um “pipe” de envio de pedidos para o gestor

– Cada processo possui um “pipe”, por onde o gestor envia a resposta ao

pedido.

• O pedido do filósofo é uma cadeia de 3 caracteres:

• O pedido do filósofo é uma cadeia de 3 caracteres:

1. Número de filósofo (‘0’+i)

2. Requerimento ('P' para pedir garfos, 'L' para libertar garfos)

3. Canal de escrita da resposta para o filósofo (‘A’+canal)

• Constantes

/* Códigos de acção */

#define GRAB 'P'

#define RELEASE 'L'

/* Códigos de resposta do gestor ao pedido de um filósofo */

#define DENY '0'

#define OK '1'

(6)

Resolução por mensagens (2)

• “Pipes” usados para comunicação

int fd[N][2];

/* gestor->filosofo (resultado) */

int request[2];

/* filosofo->gestor (pedido/libertação garfo) */

• Cada um dos 5 filósofos é um processo

void phil(

int p_numb, /* numero de filosofo 0-4 */

Programação de Sistemas

Jantar dos filósofos : 11/14

int p_numb, /* numero de filosofo 0-4 */

int quest, /* canal escrita fil->gestor */

int w_mng, /* canal escrita gestor->fil */

int r_mng /* canal leitura gestor->fil */ );

• O gestor recebe como parâmetro o canal de leitura dos

pedidos

void manager(

int in /*descritor do canal de leitura dos pedidos*/

);

Resolução por mensagens (3)

void phil( int p_numb, int quest, int w_mng, int r_mng) { for(;;) {

phil_status my_status = thinking; depict_status(p_numb,my_status); sleep( 8+(int)(random())%5 );

for(;;) { /* pede garfos */

msg[0]=GRAB; msg[1]='0'+p_numb; msg[2]='A'+w_mng; msg[3]='\0'; write(quest,msg,LEN);

read(r_mng,msg,LEN); /* espera resposta */ if(msg[0]==DENY) {

if(msg[0]==DENY) {

my_status = waiting; depict_status(p_numb,my_status); sleep(6+(int)(random())%3; } else { my_status = eating; depict_status(p_numb,my_status); sleep( 3+(int)(random())%3 ); /* liberta garfos */

msg[0]=RELEASE; msg[1]='0'+p_numb; msg[2]='A'+w_mng; msg[3]='\0'; write( quest,msg,LEN );

break; } }

} }

(7)

Resolução por mensagens (4)

void manager(int in) { int idx;

int left,right;

/* inicializa estado dos garfos */

for( idx=0;idx<N;idx++ ) busy[idx] = FALSE;

for(;;) {

read( in,msg,LEN );

Programação de Sistemas

Jantar dos filósofos : 13/14

left = msg[1]-'0';

right = (msg[1]-'0'+1)%N; if ( msg[0]==GRAB ) {

if( busy[left]==FALSE && busy[right]==FALSE ) { busy[left] = busy[right] = TRUE;

msg[0] = OK; } else msg[0] = DENY;

write( msg[2]-'A',msg,LEN ); } else busy[left] = busy[right] = FALSE; }

}

Resolução por mensagens (5)

int main(int argc, char *argv[]) { int idx;

pid_t res, f[N]; if( argc!=2 ) {

fprintf( stderr,“%s time\n“,arv[0] ); exit(1); } /* cria pipes para os filósofos */

for(idx=0; idx<PHIL_NUMB; idx++) pipe(fd[idx]); pipe(request); /* cria pipe para gestor de garfos */

[rgc@asterix JantarFilosofos]$ JF2 17 Phil number 0 is Thinking Phil number 1 is Thinking Phil number 2 is Thinking Phil number 3 is Thinking Phil number 4 is Thinking Phil number 0 is Eating Phil number 1 is Waiting Phil number 2 is Eating Phil number 3 is Waiting Phil number 4 is Waiting Phil number 0 is Thinking Phil number 2 is Thinking pipe(request); /* cria pipe para gestor de garfos */

/* lança os filósofos */

for( idx=0;idx<PHIL_NUMB;idx++ ) { res = fork();

if( res==0 ) phil(idx, request[1], fd[idx][1], fd[idx][0]); else f[idx] = res; }

res=fork(); /* lança gestor */

if( res==0 ) manager(request[0]);

sleep(atoi(argv[1])); /* adormece tempo de simulação */ /* elimina processos antes de fechar programa */

for( idx=0;idx<PHIL_NUMB;idx++ ) kill(f[idx],SIGKILL); kill( res,SIGKILL );

return 0; }

Phil number 2 is Thinking Phil number 1 is Eating Phil number 3 is Eating Phil number 4 is Waiting Phil number 1 is Thinking Phil number 3 is Thinking

Referências

Documentos relacionados

Pacientes que apresentam hipercapnia, tosse ineficaz, secreção traqueobrônquica excessiva, que vem de encontro com o estudo, onde nos pacientes do sexo masculino

A função desejabilidade teve o intuito de verificar quais as condições de tempo e concentração de ácido acético seriam ideais para se obter a extração do

A Lei nº 2/2007 de 15 de janeiro, na alínea c) do Artigo 10º e Artigo 15º consagram que constitui receita do Município o produto da cobrança das taxas

Da Silva et al (2020) estudaram a variabilidade espacial do fator k em áreas comerciais de cana-de-açúcar, causadas pelas estruturas multivariadas de perdas de carbono em

As Despesas Gerais e Administrativas (G&amp;A) foram reduzidas em 50 bps como percentual da receita líquida no 3T12, na comparação com o 3T11, em virtude de alavancagem

Segundo Éric Laurent, a psicose ordinária se caracteriza pela não resposta aos significantes-mestres tradicionais, manifestando o fim do poder do Nome-do-Pai como

Especialidade médica que trata clinicamente ou através de cirurgia das doenças do aparelho reprodutor

Proponha Proponha uma uma função função chamada chamada inicializa() inicializa() que receba um vetor de inteiros, seu que receba um vetor de inteiros, seu tamanho,