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:
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:
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: