====== Filas de mensagens ====== {{ :so:ppos_12_mqueue.mkv |Video deste projeto}} 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. ==== Inicia uma fila de mensagens ==== int mqueue_init (mqueue_t *queue, int max_msgs, int msg_size) Inicia a fila de mensagens apontada por ''queue'', com capacidade para receber até ''max_msgs'' mensagens de tamanho ''msg_size'' bytes cada, inicialmente vazia. Retorna 0 em caso de sucesso e -1 em caso de erro. Exemplo: inicia uma fila para guardar até 100 números de tipo ''double'': mqueue_t fila1 ; if ( mqueue_init (&fila1, 100, sizeof (double)) ) { printf ("Erro ao iniciar a fila\n") ; exit (1) ; } ==== Envia uma mensagem para a fila ==== int mqueue_send (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. Sugestão: copie a mensagem do //buffer// para a fila (ou vice-versa) usando funções C como ''bcopy'' ou ''memcpy''. Exemplo: Enviar o valor de uma variável para a fila ''fila1'': double pi = 3.1415926535897932 ; if ( mqueue_send (&fila1, &pi) ) { printf ("Erro ao enviar mensagem\n") ; exit (1) ; } ==== Recebe uma mensagem da fila ==== int mqueue_recv (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'': double buf ; if ( mqueue_recv (&fila1, &buf) ) { printf ("Erro ao receber mensagem\n") ; exit (1) ; } else { printf ("Recebi o valor %lf\n", buf) ; } ==== Encerra uma fila ==== int mqueue_destroy (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 (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 [[https://en.wikipedia.org/wiki/Circular_buffer|buffer circular]]. Seu código deverá funcionar com {{pingpong-mqueue.c|este programa de teste}} e deverá gerar um resultado {{pingpong-mqueue.txt|similar a este}}. A figura abaixo representa graficamente esse programa de teste: {{ :so:prod-soma-cons.png |Produtor/somador/consumidor}} ===== Outras informações ===== * Duração estimada: 6 horas. * Dependências: * [[Gestão de Tarefas]] * [[Dispatcher]] * [[Preempção por Tempo]] * [[Tarefas suspensas]] * [[Tarefas dormindo]] * [[Semáforos]]