O Produtor e o Consumidor

Este artigo tem por finalidade apresentar um problema clássico em sistemas operacionais, a relação "o produtor e o consumidor", que visa por em prática a gerência de processos concorrentes em um sistema operacional. Problema: um processo escreve em um buffer limitado, enquanto outro lê e limpa o mesmo, preservando a integridade dos dados.

[ Hits: 96.570 ]

Por: Ricardo Bocchi em 27/01/2010 | Blog: http://ricardobocchi.blogspot.com/


A solução, uma breve introdução



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*/

Página anterior     Próxima página

Páginas do artigo
   1. O problema, uma breve introdução
   2. A solução, uma breve introdução
   3. Lógica e estruturação da solução - o produtor
   4. Lógica e estruturação da solução - o consumidor
   5. Código comentado na íntegra
   6. Compilação e execução
Outros artigos deste autor
Nenhum artigo encontrado.
Leitura recomendada

Cuidado com números em Ponto Flutuante

Como funcionam os alocadores de memória do STD C?

Algum humor e C++ Design Patterns (parte 2)

A duplicação do buffer de saída na chamada de sistema fork() do Linux

Ponteiros - Saindo de Pesadelos

  
Comentários
[1] Comentário enviado por pink em 29/01/2010 - 12:51h

Ótimo, meus parabéns.... sem comentários....
Aguardo pelo próximo artigo....

[2] Comentário enviado por saitam em 15/05/2010 - 16:54h

Ótimo artigo bem didático. Parabéns
Aguardo pelo próximo artigo [2]

[3] Comentário enviado por Claudinei_Jr em 03/04/2013 - 18:06h

Ótimo Artigo, super didático!
Parabéns!
Contribuiu muito com minhas pesquisas sobre o assunto!!!


Contribuir com comentário




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts