Filas de mensagens
Este projeto faz parte do PPOS v2.
Uma fila de mensagens é uma estrutura usada pelas tarefas para comunicação através de troca de mensagens de tamanho fixo. Cada fila pode armazenar até N mensagens de tamanho fixo, respeitando uma política de acesso FIFO.
O acesso à fila é bloqueante, ou seja, uma tarefa que tenta enviar uma mensagem a uma fila cheia terá de esperar até que surjam vagas na fila; uma tarefa que deseja receber mensagens de uma fila vazia terá de esperar até que uma mensagem esteja disponível nessa fila.
As funções a implementar são descritas a seguir.
Cria uma fila de mensagens
struct mqueue_t *mqueue_create (int max_msgs, int msg_size)
Cria uma nova fila de mensagens com capacidade para receber até max_msgs mensagens de tamanho msg_size bytes cada, inicialmente vazia. Retorna um ponteiro para a nova fila ou NULL em caso de erro.
Exemplo: inicia uma fila para guardar até 100 números de tipo long:
struct mqueue_t *fila1 ; fila1 = mqueue_create(100, sizeof (long)); if (! fila1) { printf ("Erro ao iniciar a fila\n") ; exit (1) ; }
Envia uma mensagem para a fila
int mqueue_send (struct mqueue_t *queue, void *msg)
Envia a mensagem apontada por msg para o fim da fila queue; esta chamada é bloqueante: caso a fila esteja cheia, a tarefa corrente é suspensa até que o envio possa ser feito. O ponteiro msg aponta para um buffer contendo a mensagem a enviar, que deve ser copiada para dentro da fila. Retorna 0 em caso de sucesso e -1 em caso de erro.
bcopy ou memcpy.
Exemplo: Enviar o valor de uma variável para a fila fila1:
long x = 1234567890 ; if ( mqueue_send (fila1, &x) ) { printf ("Erro ao enviar mensagem\n") ; exit (1) ; }
Recebe uma mensagem da fila
int mqueue_recv (struct mqueue_t *queue, void *msg)
Recebe uma mensagem do início da fila queue e a deposita no buffer apontado por msg; esta chamada é bloqueante: caso a fila esteja vazia, a tarefa corrente é suspensa até que a recepção possa ser feita. O ponteiro msg aponta para um buffer que irá receber a mensagem. Retorna 0 em caso de sucesso e -1 em caso de erro.
Exemplo: Receber uma mensagem da fila fila1 e colocar seu valor na variável buf:
long buf ; if ( mqueue_recv (fila1, &buf) ) { printf ("Erro ao receber mensagem\n") ; exit (1) ; } else { printf ("Recebi o valor %ld\n", buf) ; }
Encerra uma fila
int mqueue_destroy (struct mqueue_t *queue)
Encerra a fila de mensagens indicada por queue, destruindo seu conteúdo e liberando todas as tarefas que esperam mensagens dela (essas tarefas devem retornar das suas respectivas chamadas com valor de retorno -1).
Retorna 0 em caso de sucesso e -1 em caso de erro.
Número de mensagens
int mqueue_msgs (struct mqueue_t *queue)
Informa o número de mensagens presentes na fila indicada por queue. Retorna 0 ou +N em caso de sucesso e -1 em caso de erro.
Observações:
Filas de mensagens são na verdade buffers limitados acessados por tarefas que produzem e consomem mensagens. O código do sistema produtor/consumidor é um bom ponto de partida para implementar as funções mqueue_send e mqueue_recv.
As filas de mensagens devem ser genéricas em relação aos tipos de mensagens suportadas. Em outras palavras, a implementação deve suportar o envio de qualquer tipo de dado de tamanho conhecido, não sendo restrita a um tipo ou dois.
O buffer interno da fila pode ser implementado com uma estrutura de buffer circular, ou pode ser usada a fila genérica já implementada.
Arquivos
Os seguintes arquivos são relevantes para este projeto:
kernel/mqueue.c: implementação das filas de mensagenstest/pingpong-mqueue.c: programa de testetest/pingpong-mqueue.txt: saída esperada do teste
O programa de teste implementa um sistema produtor-consumidor complexo, com processos que produzem e consomem valores de acordo com a arquitetura apresentada na figura abaixo:
Outras informações
- Duração estimada: 6 horas.
- Dependências:
