Laboratório de CES-33

INSTITUTO TECNOLÓGICO DE AERONÁUTICA
Aluno: Francisco Germano Batista da Silva Júnior
Professor: Edgar Toshiro Yano Data:08/05/09

O laboratório desenvolvido tem por objetivo tratar conceitos relacionados a processos e threads. Através da resolução de problemas clássicos (produtor-consumidor, jantar dos filósofos, barbeiro sonolento, escritores e leitores) ferramentas importantes dos sistemas operacionais são utilizadas (semáforos por exemplo).

Problema 1: Produtores e consumidores empregando pipes.

Considere dois grupos de processos: os produtores e o consumidores. Os produtores produzem informação e enviam para os consumidores. Os consumidores recebem a informação e fazem utilização dela. Como a quantidade de produtores e consumidores pode ser diferente, além da velocidade de produção ser diferente da velocidade de consumo, ocorrerá o risco de mensagens serem perdidas. Para evitar esse tipo de problema vários métodos podem ser empregados (Busy waiting, semáforos, monitores…) e nesse relatório foi utilizada uma pipe.

#define READ 0
#define WRITE 0
#define CONSUMERS 1
#define PRODUCERS 1
#define N 1

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct mensagem{
char c[50];
};

int pc[2], aux, j;
struct mensagem slots[CONSUMERS];
char texto[50], str[10];

void produzir(void);
void consumir(int i);

int main () { 
    pipe(pc);
    for(aux=0;aux<CONSUMERS;aux++){
        if(fork()==0){
            while(1){
                consumir(aux);
            }
        }
        else{        
            printf("OI)");        
            for(j=0;j<PRODUCERS;j++){
                if(fork()==0){
                    while(1){
                        produzir();
                    }
                }
            }
        }
    }
    while(1){;}
    exit((0));
}

void produzir(void){
    int i;
    printf("O produtor %d produz a mensagem<n", i=getpid());
    sleep(4);
    i=rand()%10;
    char c=i;
    strcpy(str,"Codigo: ");
    strcat(str,c);
    strcpy(texto,str);
    close(pc[READ]);
    write(pc[WRITE],texto, strlen(texto)+1);
    close(pc[WRITE]);    
}

void consumir(int i){
    int n;
    close(pc[WRITE]);
    read(pc[READ],slots[i].c, 50);
    close(pc[READ]);
    sleep(2);
    printf("O consumidor %d consumiu a seguinte mensagem:\n %s", n=getpid(), slots[i].c);
}

Falta ser finalizado!

Problema 2: O jantar dos filósofos

O problema consiste em 5 filósofos (podem ser mais filósofos) que se reunem ao redor de uma mesa circular. Em frente a cada filósofo há um prato com comida e entre dois pratos temos um talher. Os filósofos desempenham duas atividades que são pensar e comer. Para que o filósofo coma ele necessita de dois talheres (o que está a esquerda de seu prato e o que está a direita do seu prato). O problema consiste em desenvolver um algorítimo para que todos os filósofos comam. Caso não haja controle da ordem na qual os filósofos iniciam a sua refeição poderemos ter condições de disputa, que podem gerar deadlocks e fazer com que os filósofos não consigam se alimentar.

Segue o código que implementa uma solução para o problema através de semáforos.

#define N        5
#define LEFT        (i+N-1)%N
#define RIGHT        (i+1)%N
#define THINKING    0
#define HUNGRY        1
#define EATING        2

#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
#include <stdlib.h>

int state[N];
int n=0;
sem_t mutex, s[N];

void philosopher(int i);
void think(int i);
void eat(int i);
void take_forks(int i);
void put_forks(int i);
void test(int i);

int main(){
    pthread_t filosofos[N];
    sem_init(&mutex, 0, 1);
    while(n<N){
        pthread_create(&filosofos[n], NULL, (void *)philosopher, (int *)n);
        sem_init(&s[n],0, 0);        
        n++;
    }
    for(n=0;n<N;n++){
        pthread_join(filosofos[n], NULL);
    }
    exit((0));
}

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

void think(int i){
    printf("O filosofo %d esta pensando!\n", i);
    sleep(rand()%10);
}

void eat(int i){
    printf("O filosofo %d esta comendo\n", i);    
    sleep(rand()%10);
}

void take_forks(int i) {
    sem_wait(&mutex);
    printf("O filosofo %d esta faminto\n", i);    
    state[i] = HUNGRY;
    test(i);
    sem_post(&mutex);
    sem_wait(&s[i]);
}

void put_forks(int i) {
    sem_wait(&mutex);
    printf("O filosofo %d terminou de comer\n", i);
    state[i] = THINKING;
    test(LEFT);
    test(RIGHT);
    sem_post(&mutex);
}

void test(int i){
    if (state[i] == HUNGRY && state[LEFT] != EATING && state[RIGHT] != EATING) {
    state[i] = EATING;
    sem_post(&s[i]);
    }
}

O programa foi testado e os resultados foram satisfatórios. Segue a ilustração de um dos testes do programa:

Jantardosfilosofos.jpg

Problema 3: O barbeiro sonolento

O problema consiste de uma barbearia que possui um conjunto de barbeiros e cadeiras de espera. Um barbeiro só pode cortar o cabelo de um cliente por vez. Caso não haja nenhum cliente na barbearia para cortar o cabelo, o barbeiro dorme. Os clientes ao chegarem na barbearia tentarão cortar o cabelo. Caso não exista nenhum barbeiro disponível para corte no momento (lembrando que o cliente pode acordar um barbeiro que esteja dormindo), ele tentará aguardar em uma cadeira. Se não houver nenhuma cadeira disponível o cliente irá embora da barbearia.

A solução do problema emprega um semáforo para os barbeiros e outro semáforo para os clientes.

#define CHAIRS 5
#define CUSTOMERS 15
#define BARBERS 1

#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
#include <stdlib.h>

void barber(int i);
void cut_hair(int i);
void customer(int i);
void get_haircut(int i);

sem_t customers, barbers, mutex;
pthread_t c[CUSTOMERS], b[BARBERS];
int n, waiting = 0;

int main(){
    sem_init(&mutex, 0, 1);
    sem_init(&barbers, 0, 0);
    sem_init(&customers, 0, 0);
    for(n=0;n<BARBERS;n++)
        pthread_create(&b[n], NULL, (void *)barber, (int *)n);
    for(n=0;n<CUSTOMERS;n++){
        pthread_create(&c[n], NULL, (void *)customer, (int *)n);
        sleep(1);    
    }
    for(n=0;n<BARBERS;n++){
        pthread_join(b[n], NULL);
    }
    /*for(n=0;n<CUSTOMERS;n++){
        pthread_join(c[CUSTOMERS], NULL);
    }*/
    exit((0));
}

void barber(int i){
    printf("Barbeiro %d chegou a barbearia\n", i);
    while(1){
    sem_wait(&customers);
    sem_wait(&mutex);
    waiting = waiting - 1;
    sem_post(&barbers);
    sem_post(&mutex);
    cut_hair(i);
    }
}

void cut_hair(int i){
    printf("O barbeiro %d comeca a cortar o cabelo\n",i);
    printf("FIGARO, FIGARO, FIGARO!!!\n");
    sleep(10);
    printf("O barbeiro %d terminou de cortar o cabelo\n",i);
}

void customer(int i){
    printf("Cliente %d chegou a barbearia\n", i);
    sem_wait(&mutex);
    if(waiting<CHAIRS) {
        printf("Cliente %d esta aguardando para cortar o cabelo.\n", i);
        waiting = waiting + 1;
        sem_post(&customers);
        sem_post(&mutex);
        sem_wait(&barbers);
        get_haircut(i);
        printf("Cliente %d saiu da barbearia com o seu cabelo cortado\n", i);
        }
    else {
    printf("A barbearia esta cheia, por isso o cliente %d foi embora.\n", i);
    sem_post(&mutex);//up(&mutex);
    }
}

void get_haircut(int i){
    printf("O cliente %d tera o seu cabelo cortado agora\n",i);
    sleep(10);
}

O programa foi testado e os resultados foram satisfatórios. Segue a ilustração de um dos testes do programa:

Barbeiro01.jpg
Barbeiro02.jpg

Problema 4: Leitores e escritores

O problema dos leitores e escritores ocorre quando a competição pela utilização de um banco de dados (ou estrutura de dados). A atividade de escrever leva mais tempo do que a atividade de ler, assim cria-se uma condição de disputa como um processo tenta ler e outro escrever ao mesmo tempo.

A solução para esse problema é feita com semáforos e um mutex.

#define WRITERS 1
#define READERS 5

#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
#include <stdlib.h>

void reader(int i);
void writer(int i);
void read_data_base();
void use_data_read();
void think_up_data();
void write_data_base();

sem_t db;
pthread_mutex_t mutex;
pthread_t w[WRITERS], r[READERS];
int rc = 0, n;
int data[WRITERS];
int data_base[6];

int main(){
    for(n=0;n<6;n++)
        data_base[n]=0;
    sem_init(&db,0,1);
    pthread_mutex_init(&mutex, NULL);
    for(n=0;n<WRITERS;n++)
        pthread_create(&w[n], NULL, (void *)writer, (int *)n);
    for(n=0;n<READERS;n++)
        pthread_create(&r[n], NULL, (void *)reader, (int *)n);
    pthread_join(w[0],NULL);
    exit((0));
}

void reader(int i) {
    while(1) {
        pthread_mutex_lock(&mutex);
        rc = rc + 1;
        if (rc == 1) sem_wait(&db);
        pthread_mutex_unlock(&mutex);
        read_data_base(i);
        pthread_mutex_lock(&mutex);
        rc = rc - 1;
        if (rc == 0) sem_post(&db);
        pthread_mutex_unlock(&mutex);
        use_data_read(i);
    }        
}

void writer(int i) {
    while(1) {
        think_up_data(i);
        sem_wait(&db);
        write_data_base(i);
        sem_post(&db);
    }
}

void read_data_base(int i){
    printf("O leitor %d leu a informacao %d do banco de dados\n", i, data_base[rand()%6]);
    usleep(500000);
}

void use_data_read(int i){
    printf("O leitor %d utilizou o dado lido\n", i);
    usleep(500000);
}

void think_up_data(int i){
    data[i]=rand()%100;
    sleep(4);
    printf("O escritor %d produziu nova informacao\n",i);
}

void write_data_base(int i){
    printf("O escritor %d esta escrevendo a informacao %d no banco de dados\n", i, data[i]);
    sleep(4);
    data_base[rand()%6]=data[i];    
}

O programa foi testado e os resultados foram satisfatórios. Segue a ilustração de um dos testes do programa:

Escritor01.jpg
Escritor02.jpg
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License