Programação de Sistemas



Documentos relacionados
8 PROBLEMAS CLÁSSICOS

Programando com Threads em C

Programação de Sistemas

Sincronização de Processos (3) Exercícios - Semáforos

Produtor - Consumidor c/ Buffer Circular (1) Aula 13 - Exercícios - Semáforos. Produtor - Consumidor c/ Buffer Circular (3)

Listas ligadas/listas encadeadas

Comunicação Inter-Processo em Unix. Pipes FIFO (Named Pipes) Pipes

Algoritmos e Programação

Sincronização de Processos (3) Exercícios - Semáforos

Memória compartilhada

Sincronização de Processos (3) Exercícios - Semáforos

Linguagem de Programação C

SISTEMAS OPERACIONAIS. 2ª. Lista de Exercícios

UNIVERSIDADE FEDERAL DO ESPÍRITO SANTO CENTRO UNIVERSITÁRIO NORTE DO ESPÍRITO SANTO

Programação Estruturada I

Computação 2. Aula Profª. Fabiany Listas Duplamente Encadeadas

Comunicação entre Processos

Tipos Abstratos de Dados (TAD)

Comunicação entre Processos Named Pipes (FIFO)

Aula 3/4: Vetores/Matrizes e Ponteiros

SISTEMAS OPERACIONAIS. 2ª. Lista de Exercícios

Programando com Threads em C

Tabela ASCII de caracteres de controle

Indexação e Busca. O objetivo deste trabalho é projetar e implementar um sistema de programas para indexação e busca em arquivos de texto.

Sistemas Operacionais Processos

PROGRAMAÇÃO FUNÇÕES NA LINGUAGEM C

Listas (Parte 2) Túlio Toffolo BCC202 Aula 10 Algoritmos e Estruturas de Dados I

Sistemas Distribuídos Capítulo 4 - Aula 5

Referências. Programação de Computadores II. Cap. 7 Cadeias de Caracteres. Caracteres. Tópicos

FUNÇÕES EM C Material adaptado da profa Silvana Maria Affonso de Lara

ESTRUTURAS CONDICIONAIS. Baseado nos slides de autoria de Rosely Sanches e Simone Senger de Souza

/*(Atenção: Em se tratando de uma lista estaticamente alocada, temos utilizado a estratégia de passa o tamanho máximo do vetor.)*/

Exercícios Resolvidos (Problemas Clássicos e Outros)

Métodos Computacionais. Fila

Linguagem C: variáveis, operadores, entrada/saída. Prof. Críston Algoritmos e Programação

Simulado de Linguagem de Programação Java

MC504 Sistemas Operacionais MC514 Sistemas Operacionais: Teoria e

Computação I - C Prova /10/ Profs. Adriano Cruz e Valeria Bastos

Conversão Visualg à C++ Prof. Paulo Cesar F. de Oliveira, BSc, PhD

PIP/CA - Programa Interdisciplinar de Pós-Graduação em Computação Aplicada da UNISINOS ALGORITMOS & ESTRUTURAS DE DADOS

Trabalho Prático II - Resta 1 Data de Entrega: Conferir no calendário!

Capítulo 5: Repetições

TAD: Tipo Abstrato de Dados (parte 2)

Listas Encadeadas. David Menotti Algoritmos e Estruturas de Dados II DInf UFPR

ESTRUTURAS CONDICIONAIS. Introdução à Ciência da ComputaçãoI Simone Senger de Souza

Do alto-nível ao assembly

1 System Calls no Linux

Comunicação entre pai e filho

Criação de Processos Fork( ) Exec( )

Algoritmos e Estruturas de dados

Laboratório de Programação - Exercício 25

Curso C: Funções e Macros

Manipulação de processos

1.a) Qual a diferença entre uma linguagem de programação de alto nível e uma linguagem de programação de baixo nível?


Linguagens de Programação I

Processos. Processo (1) Processo (2) Processo (3) Conceitos Básicos

Processos. Conceitos Básicos

Comunicação entre Processos Memória Compartilhada

Métodos Computacionais. Tipos Estruturados

Sistemas Operacionais INF Prof. José Gonçalves

Transcrição:

Programação de Sistemas Jantar dos filósofos Programação de Sistemas Jantar dos filósofos : 1/14 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 do outro lado liberte o garfo. Figura 2-31, Modern Operating Systems Programação de Sistemas Jantar dos filósofos : 2/14

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. 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; Programação de Sistemas Jantar dos filósofos : 3/14 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 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 conceptualmente mais simples de implementar. Programação de Sistemas Jantar dos filósofos : 4/14

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 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]; Programação de Sistemas Jantar dos filósofos : 5/14 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 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 */ Programação de Sistemas Jantar dos filósofos : 6/14

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 */ void put_forks(int i) { sem_wait(&door); state[i] = thinking; test(left(i)); test(right(i)); sem_post(&door); Programação de Sistemas Jantar dos filósofos : 7/14 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); Programação de Sistemas Jantar dos filósofos : 8/14

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 ); 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; [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 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]$ Programação de Sistemas Jantar dos filósofos : 9/14 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: 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' Programação de Sistemas Jantar dos filósofos : 10/14

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 */ 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*/ Programação de Sistemas Jantar dos filósofos : 11/14 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) { 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; Programação de Sistemas Jantar dos filósofos : 12/14

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 ); 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; Programação de Sistemas Jantar dos filósofos : 13/14 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 */ /* 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]); [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 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 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; Programação de Sistemas Jantar dos filósofos : 14/14