Filas:introdução e serviços básicos
Veja a série RTOS Revelado
As filas foram apresentadas em um artigo anterior. Eles fornecem um meio mais flexível de passar mensagens simples entre tarefas do que as caixas de correio.
Usando filas
No Nucleus SE, as filas são configuradas no momento da construção. Pode haver no máximo 16 filas configuradas para um aplicativo. Se nenhuma fila for configurada, nenhuma estrutura de dados ou código de chamada de serviço pertencente às filas será incluído no aplicativo.
Uma fila é simplesmente um conjunto de locais de armazenamento, cada um grande o suficiente para conter um único item de dados do tipo ADDR , o acesso é controlado para que possa ser utilizado com segurança por várias tarefas. As tarefas podem gravar em uma fila repetidamente até que todos os locais estejam cheios. As tarefas podem ler de uma fila e os dados são normalmente recebidos em uma base primeiro a entrar, primeiro a sair (FIFO). Tentar enviar para uma fila cheia ou ler de uma vazia pode resultar em erro ou suspensão da tarefa, dependendo das opções selecionadas na chamada API e da configuração do Nucleus SE.
Filas e canais
O Nucleus SE também oferece suporte a tubos, que também foram introduzidos em um artigo anterior e são abordados em detalhes em um artigo futuro. A principal diferença entre filas e canais é o tamanho da mensagem. As filas transportam mensagens compreendendo um único ADDR - normalmente seriam ponteiros. Um tubo transporta mensagens com um número arbitrário de bytes de comprimento; o tamanho é fixo para cada tubo na aplicação e definido no momento da configuração.
Configuração de filas NUSE_QUEUE_SEND #define NUSE_QUEUE_NUMBER 0 / * Número de filas no Chamadas de serviço de fila Envie uma mensagem para uma fila. Implementado por NUSE_Queue_Send () no Núcleo SE. Receber uma mensagem de uma fila. Implementado por NUSE_Queue_Receive () no Núcleo SE. Envie uma mensagem para o início de uma fila. Implementado por NUSE_Queue_Jam () no Núcleo SE. Restaure uma fila para o estado não usado, sem tarefas suspensas (redefinir). Implementado por NUSE_Queue_Reset () no Núcleo SE. Fornece informações sobre uma fila especificada. Implementado por NUSE_Queue_Information () no Núcleo SE. Retorne uma contagem de quantas filas estão (atualmente) configuradas para o aplicativo. Implementado por NUSE_Queue_Count () no Núcleo SE. Adicionar uma nova fila ao aplicativo (criar). Não implementado no Nucleus SE. Remover uma fila do aplicativo (excluir). Não implementado no Nucleus SE. Retorna ponteiros para todas as filas (atualmente) no aplicativo. Não implementado no Nucleus SE. Envie uma mensagem para todas as tarefas que estão suspensas em uma fila (transmissão). Não implementado no Nucleus SE. Serviços de gravação e leitura de fila STATUS NU_Send_To_Queue (NU_QUEUE * fila, VOID * mensagem, fila - ponteiro para o bloco de controle de fila fornecido pelo usuário mensagem - um ponteiro para a mensagem a ser enviada tamanho - o número de NÃO ASSINADO elementos de dados na mensagem. Se a fila suportar mensagens de comprimento variável, este parâmetro deve ser igual ou menor que o tamanho da mensagem suportado pela fila. Se a fila suportar mensagens de tamanho fixo, este parâmetro deve ser exatamente igual ao tamanho da mensagem suportado pela fila. suspender - especificação para suspensão de tarefa; pode ser NU_NO_SUSPEND ou NU_SUSPEND ou um valor de tempo limite NU_SUCCESS - a chamada foi completada com sucesso NU_INVALID_QUEUE - o ponteiro da fila é inválido NU_INVALID_POINTER - o ponteiro da mensagem é NULL NU_INVALID_SIZE - o tamanho da mensagem é incompatível com o tamanho da mensagem suportado pela fila NU_INVALID_SUSPEND - a suspensão foi tentada a partir de um thread sem tarefa NU_QUEUE_FULL - a fila está cheia e a suspensão não foi especificada NU_TIMEOUT - a fila ainda está cheia, mesmo após a suspensão para o valor de tempo limite especificado NU_QUEUE_DELETED - a fila foi excluída enquanto a tarefa estava suspensa NU_QUEUE_RESET - a fila foi redefinida enquanto a tarefa estava suspensa STATUS NUSE_Queue_Send (NUSE_QUEUE queue, ADDR * message, fila - o índice (ID) da fila a ser utilizada mensagem - um ponteiro para a mensagem a ser enviada, que é uma variável única do tipo ADDR suspender - especificação para suspensão de tarefa; pode ser NUSE_NO_SUSPEND ou NUSE_SUSPEND NUSE_SUCCESS - a chamada foi completada com sucesso NUSE_INVALID_QUEUE - o índice da fila é inválido NUSE_INVALID_POINTER - o ponteiro da mensagem é NULL NUSE_INVALID_SUSPEND - a suspensão foi tentada a partir de um thread não-tarefa ou quando o bloqueio de chamadas de API não estava habilitado NUSE_QUEUE_FULL - a fila está cheia e a suspensão não foi especificada NUSE_QUEUE_WAS_RESET - a fila foi redefinida enquanto a tarefa estava suspensa
Número de filas
Como acontece com a maioria dos aspectos do Nucleus SE, a configuração das filas é controlada principalmente por #define declarações em nuse_config.h . A configuração principal é NUSE_QUEUE_NUMBER , que determina quantas filas são configuradas para o aplicativo. A configuração padrão é 0 (ou seja, nenhuma fila está em uso) e você pode defini-la com qualquer valor até 16. Um valor incorreto resultará em um erro de tempo de compilação, que é gerado por um teste em nuse_config_check.h (isso está incluído em nuse_config.c e, portanto, compilado com este módulo) resultando em um #error declaração sendo compilada.
A escolha de um valor diferente de zero é a “habilitação principal” para filas. Isso resulta em algumas estruturas de dados sendo definidas e dimensionadas de acordo, sobre o que falaremos no próximo artigo. Ele também ativa as configurações de ativação da API.
Ativa API
Cada função de API (chamada de serviço) no Nucleus SE tem um #define de ativação símbolo em nuse_config.h . Para filas, são:
NUSE_QUEUE_RECEIVE
NUSE_QUEUE_JAM
NUSE_QUEUE_RESET
NUSE_QUEUE_INFORMATION
NUSE_QUEUE_COUNT
Por padrão, todos eles são definidos como FALSO , desabilitando cada chamada de serviço e inibindo a inclusão de qualquer código de implementação. Para configurar filas para um aplicativo, você precisa selecionar as chamadas de API que deseja usar e definir seus símbolos de ativação para TRUE .
Aqui está um extrato do arquivo nuse_config.h padrão.
Sistema - 0-16 * /
/ * Ativadores de chamada de serviço * /
#define NUSE_QUEUE_SEND FALSE
#define NUSE_QUEUE_RECEIVE FALSE
#define NUSE_QUEUE_JAM FALSE
#define NUSE_QUEUE_RESET FALSE
#define NUSE_QUEUE_INFORMATION FALSE
#define NUSE_QUEUE_COUNT FALSE
Um erro de tempo de compilação ocorrerá se uma função API de fila estiver habilitada e nenhuma fila for configurada (exceto para NUSE_Queue_Count () que é sempre permitido). Se o seu código usar uma chamada de API, que não foi habilitada, ocorrerá um erro de tempo de link, pois nenhum código de implementação terá sido incluído no aplicativo.
O Nucleus RTOS oferece suporte a dez chamadas de serviço que pertencem às filas, que fornecem a seguinte funcionalidade:
A implementação de cada uma dessas chamadas de serviço é examinada em detalhes.
As operações fundamentais, que podem ser realizadas em uma fila, são gravar dados nela - o que às vezes é denominado envio - e lendo dados dele - que também é denominado recebimento . Também é possível gravar dados na frente de uma fila - o que também é denominado congestionamento . O Nucleus RTOS e o Nucleus SE fornecem, cada um, três chamadas API básicas para essas operações, que serão discutidas aqui.
Gravando em uma fila
A chamada da API Nucleus RTOS para gravar em uma fila é muito flexível, permitindo suspender indefinidamente ou com um tempo limite se a operação não puder ser concluída imediatamente; ou seja, você tenta gravar em uma fila cheia. O Nucleus SE fornece o mesmo serviço, exceto que a suspensão da tarefa é opcional e o tempo limite não é implementado.
O Nucleus RTOS também oferece um recurso de transmissão para uma fila, mas isso não é compatível com o Nucleus SE. Ele é descrito em APIs não implementadas no próximo artigo.
Chamada de Nucleus RTOS API para envio para uma fila
Protótipo de chamada de serviço:
tamanho UNSIGNED, UNSIGNED suspender);
Parâmetros:
Retorna:
Chamada de API do Nucleus SE para envio para uma fila
Esta chamada de API oferece suporte à funcionalidade principal da API Nucleus RTOS.
Protótipo de chamada de serviço:
U8 suspend);
Parâmetros:
Retorna:
Implementação Nucleus SE de ASend de Fila
A maior parte do código de NUSE_Queue_Send () A função API - após a verificação do parâmetro - é selecionada por compilação condicional, dependendo se o suporte para bloquear (suspender a tarefa) chamadas de API está habilitado. Veremos as duas variantes separadamente aqui.
Se o bloqueio não estiver habilitado, o código para esta chamada de API é bastante simples:
if (NUSE_Queue_Items [fila] ==NUSE_Queue_Size [fila]) / * fila cheia * / {return_value =NUSE_QUEUE_FULL;} else / * elemento de fila disponível * / {NUSE_Queue_Data [fila] [NUSE_Queue_Head [fila] ++] *mensagem; if (NUSE_Queue_Head [fila] ==NUSE_Queue_Size [fila]) {NUSE_Queue_Head [fila] =0; } NUSE_Queue_Items [fila] ++; return_value =NUSE_SUCCESS;}
A função simplesmente verifica se há espaço na fila e usa o NUSE_Queue_Head [] índice para armazenar a mensagem na área de dados da fila.
Quando o bloqueio está habilitado, o código se torna mais complexo:
faça {if (NUSE_Queue_Items [queue] ==NUSE_Queue_Size [queue]) / * queue full * / {if (suspend ==NUSE_NO_SUSPEND) {return_value =NUSE_QUEUE_FULL; } else {/ * bloquear tarefa * / NUSE_Queue_Blocking_Count [queue] ++; NUSE_Suspend_Task (NUSE_Task_Active, (fila <<4) | NUSE_QUEUE_SUSPEND); return_value =NUSE_Task_Blocking_Return [NUSE_Task_Active]; if (return_value! =NUSE_SUCCESS) {suspend =NUSE_NO_SUSPEND; }}} else {/ * elemento de fila disponível * / NUSE_Queue_Data [fila] [NUSE_Queue_Head [fila] ++] =* mensagem; if (NUSE_Queue_Head [fila] ==NUSE_Queue_Size [fila]) {NUSE_Queue_Head [fila] =0; } NUSE_Queue_Items [fila] ++; if (NUSE_Queue_Blocking_Count [fila]! =0) {índice U8; / * verificar se uma tarefa está bloqueada nesta fila * / NUSE_Queue_Blocking_Count [fila] -; para (índice =0; índice
Algumas explicações do código podem ser úteis:
O código está entre do ... while loop, que continua enquanto o parâmetro suspender tem o valor NUSE_SUSPEND .
Se a fila estiver cheia e suspender está definido para NUSE_NO_SUSPEND , a chamada da API sai com NUSE_QUEUE_FULL . Se a suspensão foi definida como NUSE_SUSPEND , a tarefa é suspensa. No retorno (ou seja, quando a tarefa é ativada), se o valor de retorno for NUSE_SUCCESS , indicando que a tarefa foi ativada porque uma mensagem foi lida (em oposição a uma redefinição da fila), o código retorna ao topo.
Se a fila não estiver cheia, a mensagem fornecida é armazenada usando o NUSE_Queue_Head [] índice para armazenar a mensagem na área de dados da fila. É feita uma verificação para saber se alguma tarefa está suspensa (aguardando para receber) na fila. Se houver alguma tarefa esperando, a primeira será ativada. O suspender variável está definida para NUSE_NO_SUSPEND e a chamada API sai com NUSE_SUCCESS .
Integrado
- Uma introdução aos Cam Locks e como funcionam
- Uma introdução aos parafusos de olho e como eles funcionam
- Uma introdução aos ilhós e como eles funcionam
- Uma introdução ao aço inoxidável e como ele é feito
- Entrada e saída básica em C#
- Caixas de correio:introdução e serviços básicos
- Semáforos:serviços utilitários e estruturas de dados
- Semáforos:introdução e serviços básicos
- Grupos de sinalizadores de evento:serviços de utilidade e estruturas de dados
- Grupos de sinalizadores de evento:introdução e serviços básicos