Para que se pudesse obter um material didático e de fácil entendimento, foram feitos alguns requisitos que julgaram-se necessários no projeto:
- O programa deve ter um buffer limitado, acessível a qualquer processo decorrente do processo principal;
- O programa deve ter uma fila apontando para o próximo endereço livre, a ser escrito;
- O programa deve ter uma fila apontando para o próximo endereço ocupado, a ser lido e liberado;
- O programa deve controlar as seções críticas (Compartilhamento de memória), para que não haja acessos ilegais.
- O programa deve ter a capacidade de colocar um processo em modo de espera;
- O programa deve ter a capacidade de controlar quando um processo está em espera, para poder "chamar" o mesmo;
- O programa deve controlar quantos endereços estão livres e quantos endereços estão ocupados.
Levando em consideração esses dados, já se tem boa parte do desenvolvimento do projeto, basta apenas conhecer as bibliotecas usadas.
Recursos:
A biblioteca mais importante do projeto foi a pthread.h, que nos proporciona a possibilidade de programação concorrente com as funções de: controle de threads, criação de threads, suspensão de threads, execução e controle de exclusão mútua por semáforos binários, para controle da seção crítica. Para maiores informações visite o site
www.yolinux.com/TUTORIALS/LinuxTutorialPosixThreads.html, de onde pesquisei todo material necessário.
Estrutura da fila:
A fila (FIFO) que controla o acesso ao buffer é formada apenas por: informação da posição atual e apontamento para próxima posição. A necessidade de se criar uma fila surgiu quando, o tempo de produzir ou de ler era diferente, gerando mais produção que leitura ou mais leitura que produção, então cada espaço do buffer que é produzido ou lido entra em uma fila e espera sua vez.
typedef struct apontador{ /* Estrutura que aponta para nova posição de leitura ou escrita.. e mantém a ordem em uma fila */
int livre; /* Posição do buffer */
struct apontador *prox; /* Próxima posição do buffer */
}APONTA;
Definições globais:
Para que houvesse o compartilhamento de memória entre os processos, foram definidas algumas variáveis e funções globais controladas por semáforos, para não haver indevidos acessos aos mesmos:
#define MAXBUFF 8 /* Máximo de buffer livre */
#define DORMINDO 0 /* Status atual do processo suspendido */
#define ACORDADO 1 /* Status atual do processo em execução */
#define ACABADO 0 /* Controle de processamento, 0 indica que produtor está produzindo */
#define PROCESSANDO 1 /* Controle de processamento, 1 indica que produtor já acabou */
APONTA *fila_leitura_inicio = NULL, *fila_leitura_fim = NULL; /* Fila que controla buffer livre de leitura */
APONTA *fila_escrita_inicio = NULL, *fila_escrita_fim = NULL; /* Fila que controla buffer livre de escrita */
void *Consumir(void* texto); /* Função do consumidor */
void *produz(void* texto); /* Função do produtor */
int setFila(int posicao, APONTA **begin, APONTA **end); /* Adiciona posição a fila que controla posições livres/ocupadas */
int getFila(APONTA **begin, APONTA **end); /* Remove posição a fila que controla posições livres/ocupadas */
char bufferLimitado[MAXBUFF]; /* Buffer de trabalho */
int buff_empty = MAXBUFF; /* Quantidade de endereços do Buffer livre */
int buff_full = 0; /* Quantidade de endereços do Buffer ocupado */
int status_produz = ACORDADO; /* Status atual do produtor é acordado */
int status_consome = ACORDADO; /* Status atual do consumidor é acordado */
int status_processamrnto = PROCESSANDO; /* Inicia status ativo de processamento */
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; /* Mutex (Semáforo) que controla o acesso ao buffer*/
pthread_mutex_t mutex_status_buff = PTHREAD_MUTEX_INITIALIZER; /* Mutex (Semáforo) que controla a espera(dormir/acordar)*/
pthread_cond_t status_produtor = PTHREAD_COND_INITIALIZER; /* Suspende execução da Thread produtor*/
pthread_cond_t status_consumidor = PTHREAD_COND_INITIALIZER; /* Suspende execução da Thread consumidor*/