Docsity
Docsity

Prepare-se para as provas
Prepare-se para as provas

Estude fácil! Tem muito documento disponível na Docsity


Ganhe pontos para baixar
Ganhe pontos para baixar

Ganhe pontos ajudando outros esrudantes ou compre um plano Premium


Guias e Dicas
Guias e Dicas


Tp - so, Exercícios de Redes de Computadores

Exercicios de Sistema de Operacionais, Inclui códigos em C em Linux, chamadas de sistema em Windows e Linux

Tipologia: Exercícios

2011

Compartilhado em 03/04/2011

rodrigo-faria-16
rodrigo-faria-16 🇧🇷

1

(1)

1 documento

1 / 19

Toggle sidebar

Esta página não é visível na pré-visualização

Não perca as partes importantes!

bg1
PONTIFÍCIA UNIVERSIDADE CATÓLICA DE MINAS GERAIS
Instituto de Informática - Campus São Gabriel - Curso de Sistemas de
Informação
Sistemas Operacionais (SO) - Professor: Paulo Amaral
LISTA DE EXERCÍCIOS PRÁTICA E LABORATÓRIO 1/07
Ex1:
Fazer programas em e C (compilador gcc Linux/Unix) usando
obrigatoriamente através parâmetros na linha de comando p e utilizando na
versão final dos programas em C somente funções de biblioteca de E/S
(stdio) do C (como printf, scanf, etc.), não utilize nenhum método de C++
como cin e cout, com as seguintes especificações :
1.1
Pesquisar em um intervalo fechado de números inteiros [MIN ... MAX] , ou
seja, delimitado pelos valores inteiros MIN e MAX recebidos
obrigatoriamente através parâmetros na linha de comando (C), e imprimir
os números que são simultaneamente ímpar, múltiplo de 7 e não múltiplo de
5.
Exemplo (com: MIN = 2 e MAX = 10):
ENTRADA: ./intervalo.exe 2 10
SAÍDA: 7
#include<stdio.h>
int main(int argc,char **argv){
int i = 0;
int min = atoi(argv[1]);
int max = atoi(argv[2]);
printf("SHAWYSON SALVIO, MARCELO VIEIRA, RODRIGO
FARIA, ROBERTA \n\n");
printf("Resultado:");
for(i = min; i <=max ; i++)
if((i % 2 != 0) && (i % 7 == 0) && (i % 5 != 0))
printf("%d ",i);
printf("\n\n");
return 0;
}
1.2
Implementar uma calculadora com as quatro operações aritméticas básicas
(+, -, x e / ). Os operandos e o operador são recebidos obrigatoriamente
através parâmetros na linha de comando (shell script e C). Exemplo:
ENTRADA: ./calcl.exe 2 x 3
SAÍDA: 2 x 3 = 6
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff
pf12
pf13

Pré-visualização parcial do texto

Baixe Tp - so e outras Exercícios em PDF para Redes de Computadores, somente na Docsity!

PONTIFÍCIA UNIVERSIDADE CATÓLICA DE MINAS GERAIS

**Instituto de Informática - Campus São Gabriel - Curso de Sistemas de Informação Sistemas Operacionais (SO) - Professor: Paulo Amaral LISTA DE EXERCÍCIOS PRÁTICA E LABORATÓRIO 1/ Ex1: Fazer programas em e C (compilador gcc Linux/Unix) usando obrigatoriamente através parâmetros na linha de comando p e utilizando na versão final dos programas em C somente funções de biblioteca de E/S (stdio) do C (como printf, scanf, etc.), não utilize nenhum método de C++ como cin e cout, com as seguintes especificações :

Pesquisar em um intervalo fechado de números inteiros [MIN ... MAX] , ou seja, delimitado pelos valores inteiros MIN e MAX recebidos obrigatoriamente através parâmetros na linha de comando (C), e imprimir os números que são simultaneamente ímpar, múltiplo de 7 e não múltiplo de

Exemplo (com: MIN = 2 e MAX = 10): ENTRADA: ./intervalo.exe 2 10 SAÍDA: 7**

#include<stdio.h>

int main(int argc,char **argv){

int i = 0;

int min = atoi(argv[1]);

int max = atoi(argv[2]);

printf("SHAWYSON SALVIO, MARCELO VIEIRA, RODRIGO

FARIA, ROBERTA \n\n");

printf("Resultado:");

for(i = min; i <=max ; i++)

if((i % 2 != 0) && (i % 7 == 0) && (i % 5 != 0))

printf("%d ",i);

printf("\n\n");

return 0;

Implementar uma calculadora com as quatro operações aritméticas básicas (+, -, x e / ). Os operandos e o operador são recebidos obrigatoriamente através parâmetros na linha de comando (shell script e C). Exemplo: ENTRADA: ./calcl.exe 2 x 3 SAÍDA: 2 x 3 = 6

#ALUNOS: RODRIGO FARIA TAVARES

# MARCELO VIEIRA

# SHAWYSON SALVIO GOMES DE ALMEIDA

# ROBERTA MARIANA EMILIANO DE ALMEIDA

#!/bin/bash if [ -z "$1" ] || [ -z "$2" ] || [ -z "$3" ]; then echo "Entre dois numeros e um operador" echo "Exemplo: ./cal 2 + 2" exit 0 fi array[0]=$1 # Primeiro operando array[1]=$2 # Operador aritmetico array[2]=$3 # Segundo operando if [ "${array[1]}" == "+" ]; then echo "Resultado da Adição:" expr ${array[0]} + ${array[2]} fi if [ "${array[1]}" == "-" ]; then echo "Resultado da Subtração:" expr ${array[0]} - ${array[2]} fi if [ "${array[1]}" == "/" ]; then echo "Resultado da divisao:" expr ${array[0]} / ${array[2]} fi if [ "${array[1]}" == "*" ]; then echo "Resultado da Multiplicação:" expr "${array[0]}" * "${array[2]}" fi

#include<stdlib.h>

#include<stdio.h>

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

float num1,num2;

char operacao;

num1 = atof(argv[1]);

num2 = atof(argv[3]);

operacao = *argv[2];

if(operacao == '-'){

printf("RESULTADO: %f", num1 - num2);

else if(operacao =='+'){

printf("RESULTADO: %f", num1 + num2);

Ide: Esse diretório carrega informações sobre dispositivos IDE no seu sistema, cada canal IDE é representado por um diretório separado, assim como para /proc/ide/ide0 e /proc/ide/ide1. Interrupts: esse arquivo contem os registros do numeros de interrupções por IRQ na arquitetura x86. Iomem: esse arquivo mostra um mapa corrente do sistema de memória para cada dispositivo físico. Ioports: o arquivo de saida produz uma lista corrente de regiões de portas registradas para uso de comunicação I/O com algum dispositivo. Irq: Este diretório é usado para configurar IRQS para CPU, que permite sistemas conectem a uma irq particular para somente um CPU. Cada IRQ tem sem próprio diretório, permitindo configuração individual para cada IRQ. Kcore: esse arquivo representa a memoria fisica do sistema, e grava arquivos no formato core. Locks: este arquivo mostra os os arquivos correntes liberados pelo kernel. O conteúdo desse arquivo contem um kernel interno de debug de dados e pode variar , dependendo do uso do sistemas. Misc: esse arquivo lista drivers registrados em miscellaneous Partitions : Most of the information here is of little importance to the user, except for the following columns:

  • major — The major number of the device with this partition. The major number in our example ( 3 ) corresponds with the block device ide0 in /proc/devices.
  • minor — The minor number of the device with this partition. This serves to separate the partitions into different physical devices and relates to the number at the end of the name of the partition.
  • #blocks — Lists the number of physical disk blocks contained in a particular partition.
  • name — The name of the partition Pci : o arquivo contem a lista completa de cada dispositivo no sistema Stat : esse arquivo mantem trilhas de variedades de diferentes estatísticas sobre o sistema desde que ele tenha sido reiniciado. Swaps : esse arquivo mede a quantidade de espaço do swap e sua utilização. Processador: Pentium 4 1.70 GHZ Memória RAM: 512 Mb; Disco Rígido: Maxtor de 40 Gb de 7.200 RPM; Placa de Vídeo: Nvidia de 128 Mb; Sistemas Operacionais: Windows XP Professional SP2 e Debian Etch 4. debian:~# cat /proc/cpuinfo

processor : 0 vendor_id : GenuineIntel cpu family : 15 model : 1 model name : Intel(R) Pentium(R) 4 CPU 1.70GHz stepping : 2 cpu MHz : 1715. cache size : 256 KB fdiv_bug : no hlt_bug : no f00f_bug : no coma_bug : no fpu : yes fpu_exception : yes cpuid level : 2 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm up bogomips : 3433. Tabela de Interrupções (cat /proc/interrupts) CPU 0: 964773 XT-PIC timer 1: 573 XT-PIC i 2: 0 XT-PIC cascade 5 : 0 XT-PIC SI 6 : 5 XT-PIC floppy 7 : 1 XT-PIC parport 8 : 1 XT-PIC rtc 9 : 1 XT-PIC acpi 10 : 0 XT-PIC ehci_hcd:usb4, eth 11 : 2632 XT-PIC ohci_hcd:usb1, ohci_hcd:usb2, ohci_hcd:usb3, eth 12 : 8247 XT-PIC i 14 : 20249 XT-PIC ide 15 : 68022 XT-PIC ide NMI: 0 LOC 964746 ERR: 0 MIS Tabela de Endereços de portas (cat /proc/ioports) 0000-001f Dma 0020-0021 pic 0040-0043 timer 0050-0053 timer

HighTotal 0 kB HighFree 0 kB LowTotal 386872 kB LowFree 25424 kB SwapTotal 819272 kB SwapFree 819272 kB Dirty 0 kB Writeback 0 kB AnonPages 110384 kB Mapped 42996 kB Slab 68760 kB PageTables 1384 kB NFS_Unstable 0 kB Bounce 0 kB CommitLimit 1012708 kB Committed_AS 308692 kB VmallocTotal 638968 kB VmallocUsed 2652 kB VmallocChunk 635996 kB

Usando um computador de laboratórios ou um computador pessoal de um componente do grupo com o sistema operacional Windows. Fazer tabelas contendo os vetores de interrupção de hardware, o endereço das portas de E/S e o mapa de memória. O Computador do grupo deve ser especificado (hardware e software).Dica : Iniciar-programas - acessórios - ferramentas de sistema – informações de sistema. Ex 3: 3.1 Descreva (justificando) o que acontece com as sequências de comandos a seguir:

  1. ps 2 )sleep 10000 & 3 )ps
  2. kill – SIGKILL PID # OBS : PID é o número do processo criado. 5)ps Linha 1 : mostra os processos ativos pelo processador Linha 2 : executa o comando sleep, que aguarda 10.000 segundos para liberar o acesso a linha de comando Linha 3 : mostra o processo sleep em execução Linha 4 : mata o processo sleep Linha 5 :mostra status do processo como ‘morto’ 3. Fazer uma relação e uma breve descrição da finalidade e dos parâmetros das chamadas de sistema do Linux e Windows (NT->2003) para tratar de processos e threads (comunicação, gerenciamento e sincronização). Dicas para o Linux: livro-texto, Livro ALP, manuais e ajudas do Linux: man 2 intro > intro.sc ( No PUX ou Linux local) man 2 syscalls > syscalls.txt ( No PUX ou Linux local) Dicas para o Windows: livro-texto e manuais e ajudas do Borland C++ Builder e Windows.

Tipos de Chamadas de sistemas para Processos no Linux Na maioria dos casos não é necessário invocar chamadas de sistemas diretamente, mas podem haver situações onde a biblioteca padrão não implementa uma boa função para você. Neste caso o programador deve manualmente invocar uma chamada de sistema, usando qualquer uma das macros do de chamadas de sistema ou a função syscall(). Exemplo: #include <linux/unistd.h> A _syscall macro Chamada de sistema desejada Configuração: é importante saber que chamadas de sistema é um protótipo.Você precisa saber como sobre muitos argumentos, relativos a seus tipos e as funções de retorno do tipo. Existem seis macros de chamadas de sistemas que pode fazer chamadas para um sistema facilmente. Uma das formas: _syscallX(type,name,type1,arg1,type2,arg2,...)

  • Onde X varia de 1 a 5, e dado o número de elementos as serem usados na sua chamada.
  • type : o retorno do tipo da chamada de sistema.
  • name : nome da chamada de sistema
  • typeN : é o tipo do argumento
  • argN : é o nome do tipo de argumento Esses macros criam uma função pelo nome a qual foi chamado, com os argumentos que você especificar.Uma vez que você inclui a _syscall no seu arquivo fonte, você ira realizar uma chamada de sistema pelo nome que você definir. Tipos de chamadas de sistemas de processos em Windows O Windows NT permite a execução de aplicações escritas para outros sistemas operacionais, cujo suporte é feito a partir de subsistemas que são implementados como processos separados e fornecem um ambiente de execução compatível com a aplicações. Tal ambiente é composto por uma interface gráfica, um interpretador de comandos, uma interface de programação compatível com as chamadas do sistema implementado pelo subsistema. A estrutura do Windows NT divide-se em duas partes. A primeira é o modo usuário, onde se localizam os subsistemas protegidos, que residem em processos separados e interagem uns com os outros através do LPC (Local Procedure Call), um mecanismo de trocas de mensagens. A segunda é o modo kernel (o executivo), onde rodam os componentes que necessitam desempenho e por isso não se sujeitam a trocas de contexto e de modo em sua interação uns com os outros ou com o hardware.

a que ela pertence. Um objeto processo recebe na sua criação, uma prioridade que varia de zero a quinze e cada thread recebe uma prioridade variando de duas unidades para cima ou para baixo da prioridade do processo. O critério usado para variar a prioridade de uma thread é o tempo de uso do processador. Se a thread é interrompida por usar todo o quantum de tempo que lhe foi atribuído, o escalonador do Windows 2000 reduz sua prioridade, caso contrário sua prioridade é aumentada. Tipos de chamadas mais utilizadas em Sistemas Operacionais Linux e Windows _access(2) - verifica se o processo tem permissão para leitura, escrita ou execução de um arquivo acct(2) - muda o processo de contabilidade para ligado ou desligado alarm(2) - define um alarme de relógio para envio de um sinal chdir(2) - muda o diretório de trabalho close(2) - encerra um descritor de arquivo creat(2) - abre e cria arquivos e/ou dispositivos exec(2) - executa um arquivo execve(2) - executa programa _exit(2) - termina o processo atual fork1(2) - cria um novo processo fork(2) - cria um processo filho getpid(2) - pega a identificação do processo getppid(2) - obtém a identidade do processo. Retorna a ID do processo pai do processo atual kill(2) - envia um sinal específico para um determinado processo link(2) - renomeia um arquivo _lwp_cond_signal(2) - sinal para comunicação entre threads ou LWP _lwp_cond_wait(2) - threads esperando a ocorrência de um evento _lwp_create(2) - cria uma nova thread _lwp_kill(2) - envia um sinal para uma thread _lwp_mutex_lock(2) - realiza exclusão mutua de uma thread _lwp_self(2) - identifica uma thread lwp_wait(2) - espera pelo término de uma thread mkdir(2) - cria diretórios nice(2) - muda prioridade de um processo open(2) - abre e possibilita a criação de arquivos ou dispositivos pause(2) - aguarda por um sinal pipe(2) - cria um canal de interprocessos pset_assign(2) - constrói conjuntos de processos read(2) - leitura de arquivo rmdir(2) - remove diretórios vazios semctl(2) - realiza operações de controle de semáforos semop(2) - realiza operações de semáforos shmat(2) - operações de memória particionada shmctl(2) - controle de memória compartilhada sigsend(2) - envia sinal para um processo ou grupo de processos ulimit(2) - pega e seleciona limites de processo uname(2) - exibe informações do sistema vfork(2) - cria um processo filho e bloqueia o processo pai wait(2) - espera o processo filho terminar waitid(2) - espera um processo filho para mudança de estado waitpid(2) - espera pelo término de um processo write(2) - envia uma mensagem para outro usuário

chrroot – executa o comando ou Shell interativo com diretório raiz especial. Chamadas de sistemas Operacionais Win CreateProcess - Cria um novo processo CreateThread - Cria um novo thread em um processo existente CreateFiber - Cria um novo filamento ExitProcess - Termina o processo atual e todos os seus threads ExitThread - Termina este thread ExitFiber - Termina este filamento SetPriorityClass - Define a classe de prioridade para um processo SetThreadPriority - Define a prioridade de um thread CreateSemaphore - Cria um novo semáforo CreateMutex - Cria um novo mutex OpenSemaphore - Abre um semáforo existente openMutex - Abre um mutex existente WaitForSingleObject - Bloqueia em um único semáforo, mutex. WaitForMultipleObjects - Bloqueia em um conjunto de objetos cujos manipuladores são dados PulseEvent - Torna um evento sinalizado e depois não sinalizado ReleaseMutex - Libera um mutex para permitir que outro thread o adquira RealeseSemaphore - Incrementa o contador do semáforo EnterCriticalSection - Adquire um impedimento em uma seção crítica LeaveCriticalSection - Libera o impedimento em uma seção crítica Ex 4: Edite, compile e rode (no gcc/Linux) os programas fork1.c e fork2.c (mostrados a seguir), escreva e explique (justificando) cada linha que será impressa na tela 4. //ALUNOS: RODRIGO FARIA TAVARES // MARCELO VIEIRA // SHAWYSON SALVIO GOMES DE ALMEIDA // ROBERTA MARIANA EMILIANO DE ALMEIDA /* programa fork1.c - ref SOC - SGG-CAMPUS pg 71 / #include <stdio.h> / para printf / #include <unistd.h> / para fork, getpid, wait e exit / #include <sys/types.h> / para fork, getpid, wait e exit / int main(int argc, char * argv[]) { int x; //variável receberá o número do processo criado x = fork(); / cria processo / if(x<0) { / ocorreu erro / se o processo for menor que zero fprintf(stderr,"fork falhou"); //função(stderr) envia mensagem para a tela exit(-1); //fecha o programa pois não retornou Zero } else if(x==0){ / codigo do filho */ printf("\nPID = %d :\n\n",getpid()); //getpid() obtém o No do processo //e o imprime em tela.

Considere que PID = 1000 + NMAT%20 e que o sistema operacional cria um processo com número de identificação PID para executar o programa provaso.exe e que os processos criados pelo programa provaso.exe recebem números de identificação de processo seqüenciais: PID + 1, PID + 2, PID + 3, etc. Escreva o que será impresso pelo programa na tela, os valores assumidos por todas as variáveis (nos comandos nos quais elas são referenciadas) e todos os cálculos necessários (somente a resposta não será considerada). //ALUNOS: RODRIGO FARIA TAVARES // MARCELO VIEIRA // SHAWYSON SALVIO GOMES DE ALMEIDA // ROBERTA MARIANA EMILIANO DE ALMEIDA /* programa provaso.c - ref SOC - SGG-CAMPUS pg 71 / #include <stdio.h> / para printf / #include <unistd.h> / para fork, getpid, wait e exit / #include <sys/types.h> / para fork, getpid, wait e exit / int main(int argc, char * argv[]) { int i, j, k, p; //variaveis for (i = 1 ; i < argc; i++) //ficara em loop enquanto tiver existirem parametros { //argc tera o valor da qtde de parametros passados //por convencao o p que recebe o processo a ser criado tem o valor igual a //zero. Por isso quando executa o programa o p sempre esta igual a zero //pois é um processo filho. é a maneira do SO diferenciar o que é filho. p = fork(); / cria processo / if(p < 0) { / ocorreu erro / fprintf(stderr,"fork falhou");//funcao que imprime a string se der erro. exit(-1); //finaliza o programa caso de erro, nao retorne zero } //por convensao do SO, todo processo filho recebe 0, por isso p = 0. else if(p==0) //p = 0 pois eh status do filho { / codigo do filho / printf("\n p = %d PID = %d : %s \n", p, getpid(), argv[i]); //imprime a linha referente exit(0);//termina ok //ao status/PID filho/parametro } //passado. else { / codigo do pai */ wait(NULL );//suspende a execucao ate a morte do filho printf("\ni = %d p = %d PID = %d\n",i, p, getpid()); //imprime o indice do loop, o PID do

//filho, o PID Pai que originou o pro- }//for //cesso filho. Como recursao. exit(0); /* termina ok */ } Ex 6: Edite, compile e rode (no gcc/Linux) o programa (fork3.c ) com as seguintes especificações:

  • O programa deve receber até nove parâmetros na linha de comando (LC).
  • Para cada parâmetro recebido deve ser criado um processo.
  • Cada processo criado deve permanecer em loop infinito ( while(1) ) escrevendo na tela sua identificação e o parâmetro correspondente.
  • Abra uma outra janela no terminal e elimine individualmente, através linha de comando , cada processo criado. Obs: Veja os programas exemplo fork1.c, fork2.c e provaso.c dos exercícios anteriores. //ALUNOS: RODRIGO FARIA TAVARES // MARCELO VIEIRA // SHAWYSON SALVIO GOMES DE ALMEIDA // ROBERTA MARIANA EMILIANO DE ALMEIDA #include <stdio.h> /* para printf / #include <unistd.h> / para fork, getpid, wait e exit / #include <sys/types.h> / para fork, getpid, wait e exit */ int main(int argc, char * argv[]) { int PID; //recebera o No Processo int cont = 1; //contador limite para o numero de parâmetros if(argc > 10) { printf("\nErro: No parametros > 9\n\n"); exit(0); } while(cont < argc) //para restringir o total de parâmetros { PID = fork(); //PID recebe o No processo criado if(PID == 0) //Se o processo for o filho { while(1)//loop infinito = while(true) printf("\nFILHO: %d \n\nNo Processo: %d argv[%d] = %s",cont, getpid(), cont, argv[cont]); } if(PID < 0) printf("Criacao do 'fork' falhou!"); //se processo não foi criado cont++; //contador para incremetar o total de parametros a ser recebido.

Ex 8: Faça um programa usando threads, semáforos ou monitores que resolva um dos seguintes problemas:

**- Filósofos comedores,

  • Barbeiro dorminhoco**
  • Leitores e escritores //ALUNOS: RODRIGO FARIA TAVARES // MARCELO VIEIRA // SHAWYSON SALVIO GOMES DE ALMEIDA // ROBERTA MARIANA EMILIANO DE ALMEIDA #include <pthread.h> #include <stdio.h> #include <unistd.h> #include <stdlib.h> #define NUM_CLIENTES 5 #define NUM_CADEIRAS 2 #define CORTESMAX 8 #define TRUE 1 #define FALSE 0 typedef char BOOL; typedef struct { unsigned id; unsigned senha; char *nome; unsigned tamanho_do_cabelo; }CLIENTE; char *nomes[]={"SHAWYSON” “SALVIO”, “MARCELO VIEIRA”, “RODRIGO FARIA”, “ROBERTA"}; unsigned numero_de_clientes = 0; unsigned numero_de_cortes = 0; CLIENTE cliente[NUM_CLIENTES]; BOOL barbearia_aberta = TRUE; pthread_mutex_t barbearia_mutex; pthread_cond_t barbeiro_cond; pthread_cond_t cliente_corta_cond; pthread_cond_t cliente_espera_cond; void *thread_barbeiro(void *param); void *thread_cliente(void *fc); void pega_cliente(void); void corta_cabelo(void); void libera_cliente(void); BOOL pega_senha(CLIENTE *ficha_do_cliente); void senta_na_cadeira(CLIENTE *ficha_do_cliente);

void levanta_da_cadeira(CLIENTE *ficha_do_cliente); int main(int argc, char * argv[]) { int i; if(argc > 1) { for(i = 0; i < 8; printf("\n"), i++); //espaco na tela printf("\n\nDEBORA BRUMER!\n"); printf("RODRIGO FARIA\n"); printf("MARCELO VIEIRA\n"); printf("ROBERTA\n"); printf("\nPROGRAMA: Barbeiro Dorminhoco.\n"); printf("Simulacao do barbeiro dorminhoco.\n"); printf("Entrada: executar ./exer8\n"); printf("Saida..: Exibira o dia do barbeiro dorminhoco\n"); for(i = 0; i < 8; printf("\n"), i++); //espaco na tela } else { pthread_t threads[NUM_CLIENTES+1]; unsigned i; pthread_create(&threads[0], NULL, thread_barbeiro, NULL); for(i=0; i<NUM_CLIENTES; i++) { cliente[i].id = i; cliente[i].nome = nomes[i]; cliente[i].tamanho_do_cabelo = 1000; pthread_create(&threads[i+1], NULL, thread_cliente, (void *)&cliente[i]); } for (i=0; i<(NUM_CLIENTES+1); i++) pthread_join(threads[i], NULL); pthread_mutex_destroy(&barbearia_mutex); pthread_cond_destroy(&cliente_corta_cond); pthread_cond_destroy(&cliente_espera_cond); pthread_exit(NULL); }//else } //======================================================================= ============= void *thread_barbeiro(void *param) { while ((numero_de_cortes <= CORTESMAX ) || (numero_de_clientes != 0)) {

void *thread_cliente(void *fc) { CLIENTE *ficha_cliente; ficha_cliente = (CLIENTE )fc; while(barbearia_aberta == TRUE) { pega_senha(ficha_cliente); usleep(ficha_cliente->tamanho_do_cabelo100); } pthread_exit(NULL); } //======================================================================= ================ BOOL pega_senha(CLIENTE *ficha_do_cliente) { BOOL retorno=FALSE; pthread_mutex_lock(&barbearia_mutex); printf("Sistema: %s entra na barbearia.\n", ficha_do_cliente-

nome); if(numero_de_clientes < NUM_CADEIRAS) { numero_de_clientes++; printf("Sistema: %s aguarda para o corte.\n", ficha_do_cliente- nome); pthread_cond_signal(&barbeiro_cond); pthread_cond_wait(&cliente_espera_cond, &barbearia_mutex); printf("%s: Minha vez.\n", ficha_do_cliente->nome); pthread_cond_wait(&cliente_corta_cond, &barbearia_mutex); } else { printf("%s: Barbearia cheia! Voltarei mais tarde.\n", ficha_do_cliente->nome); } pthread_mutex_unlock(&barbearia_mutex); return retorno; }//fim main