Buzones de correo:introducción y servicios básicos
Ver la serie RTOS Revealed
Los buzones de correo se introdujeron en un artículo anterior. Son quizás el segundo método más simple de comunicación entre tareas, después de las señales, compatible con Nucleus SE. Proporcionan un medio de bajo costo, pero flexible, para pasar mensajes simples entre tareas.
Uso de buzones
En Nucleus SE, los buzones de correo se configuran en el momento de la compilación. Puede haber un máximo de 16 buzones de correo configurados para una aplicación. Si no se configuran buzones de correo, la aplicación no incluye estructuras de datos ni códigos de llamada de servicio pertenecientes a los buzones de correo.
Un buzón es simplemente una ubicación de almacenamiento, lo suficientemente grande como para contener una sola variable de tipo ADDR , cuyo acceso está controlado para que pueda ser utilizado de forma segura por múltiples tareas. Una tarea puede escribir en un buzón. Entonces está lleno y no se le puede enviar ninguna tarea hasta que una tarea realice una lectura en el buzón o se restablezca el buzón. Intentar enviar a un buzón lleno o leer desde uno vacío puede resultar en un error o la suspensión de la tarea, según las opciones seleccionadas en la llamada API y la configuración de Nucleus SE.
Buzones de correo y colas
En algunas implementaciones de SO, los buzones de correo no se implementan y se recomienda el uso de una cola de entrada única como alternativa. Esto suena razonable, ya que dicha cola proporcionaría la misma funcionalidad que un buzón de correo. Sin embargo, una cola es una estructura de datos bastante más compleja que un buzón de correo y conlleva una sobrecarga considerablemente mayor en datos (punteros de cabeza y cola, etc.), código y tiempo de ejecución.
Con Nucleus SE, como Nucleus RTOS, puede elegir entre ambos tipos de objetos y puede tomar la decisión por sí mismo.
Vale la pena considerar el enfoque alternativo si su aplicación incluye varias colas, pero quizás un solo buzón. Reemplazar ese buzón con una cola incurrirá en una pequeña sobrecarga de datos, pero elimina todo el código API relacionado con el buzón. Sería muy fácil configurar la aplicación en ambos sentidos y comparar las huellas de memoria y el rendimiento.
Las colas se discutirán en artículos futuros.
Configuración de buzones
Número de buzones
Como ocurre con la mayoría de los aspectos de Nucleus SE, la configuración de los buzones de correo se controla principalmente mediante #define declaraciones en nuse_config.h . La configuración de la clave es NUSE_MAILBOX_NUMBER , que determina cuántos buzones de correo están configurados para la aplicación. La configuración predeterminada es 0 (es decir, no hay buzones de correo en uso) y puede establecerlo en cualquier valor hasta 16. Un valor erróneo resultará en un error de tiempo de compilación, que es generado por una prueba en nuse_config_check.h (esto está incluido en nuse_config.c y por lo tanto compilado con este módulo) resultando en un #error declaración que se está compilando.
La elección de un valor distinto de cero es la "habilitación maestra" para los buzones de correo. Esto da como resultado que algunas estructuras de datos se definan y dimensionen en consecuencia, de las cuales hablaremos más en el próximo artículo. También activa la configuración de habilitación de API.
API habilitadas
Cada función de API (llamada de servicio) en Nucleus SE tiene un #define habilitante símbolo en nuse_config.h . Para los buzones de correo, estos son:
NUSE_MAILBOX_SEND
NUSE_MAILBOX_RECEIVE
NUSE_MAILBOX_RESET
NUSE_MAILBOX_INFORMATION
NUSE_MAILBOX_COUNT
De forma predeterminada, todos estos están configurados como FALSO . , deshabilitando así cada llamada de servicio e inhibiendo la inclusión de cualquier código de implementación. Para configurar buzones de correo para una aplicación, debe seleccionar las llamadas a la API que desea usar y establecer sus símbolos de habilitación en TRUE .
A continuación, se muestra un extracto del nuse_config.h predeterminado. archivo.
/ * Número de buzones de correo en el sistema - 0-16 * / #define NUSE_MAILBOX_NUMBER 0 / * Habilitadores de llamadas de servicio:* / #define NUSE_MAILBOX_SEND FALSE #define NUSE_MAILBOX_RECEIVE FALSE #define NUSE_MAILBOX_RESET FALSE #define NUSE_MAILBOX_INFORMATION FALSE #define NUSE_MAILBOX_COUNT FALSE
Se producirá un error de tiempo de compilación si se habilita una función de API de buzón de correo y no se configuran buzones de correo (excepto NUSE_Mailbox_Count () que siempre está permitido). Si su código utiliza una llamada a la API, que no se ha habilitado, se producirá un error de tiempo de enlace, ya que no se habrá incluido ningún código de implementación en la aplicación.
Llamadas de servicio del buzón
Nucleus RTOS admite nueve llamadas de servicio que pertenecen a los buzones de correo, que brindan la siguiente funcionalidad:
-
Envía un mensaje a un buzón. Implementado por NUSE_Mailbox_Send () en Nucleus SE.
-
Reciba un mensaje de un buzón. Implementado por NUSE_Mailbox_Receive () en Nucleus SE.
-
Restaura un buzón al estado no utilizado, sin tareas suspendidas (restablecer). Implementado por NUSE_Mailbox_Reset () en Nucleus SE.
-
Proporciona información sobre un buzón específico. Implementado por NUSE_Mailbox_Information () en Nucleus SE.
-
Devuelve un recuento de cuántos buzones de correo están (actualmente) configurados para la aplicación. Implementado por NUSE_Mailbox_Count () en Nucleus SE.
-
Agregar un nuevo buzón a la aplicación (crear). No implementado en Nucleus SE.
-
Eliminar un buzón de la aplicación (eliminar). No implementado en Nucleus SE.
-
Devuelve punteros a todos los buzones (actualmente) de la aplicación. No implementado en Nucleus SE.
-
Envía un mensaje a todas las tareas que están suspendidas en un buzón (difusión). No implementado en Nucleus SE.
La implementación de cada una de estas llamadas de servicio se examina en detalle.
Servicios de lectura y escritura del buzón
Las operaciones fundamentales, que se pueden realizar en un buzón, son escribir datos en él, lo que a veces se denomina envío o publicar - y leer datos de él, lo que también se denomina recibir . Nucleus RTOS y Nucleus SE proporcionan dos llamadas API básicas para estas operaciones, que se analizarán aquí.
Escribir en un buzón
La llamada a la API de Nucleus RTOS para escribir en un buzón es muy flexible, lo que le permite suspender indefinidamente, o con un tiempo de espera, si la operación no se puede completar de inmediato; es decir, intenta escribir en un buzón lleno. Nucleus SE proporciona el mismo servicio, excepto que la suspensión de tareas es opcional y el tiempo de espera no está implementado.
Nucleus RTOS también ofrece la posibilidad de transmitir a un buzón de correo, pero Nucleus SE no lo admite. Se describirá en API no implementadas . en el próximo artículo.
Llamada a la API Nucleus RTOS para enviar a un buzón
Prototipo de llamada de servicio:
STATUS NU_Send_To_Mailbox (NU_MAILBOX * buzón, mensaje VOID *, SUSPENDER SIN FIRMAR);
Parámetros:
buzón - puntero al buzón que se utilizará
mensaje - un puntero al mensaje que se va a enviar que tiene cuatro sin firmar elementos
suspender - especificación para la suspensión de tareas; puede ser NU_NO_SUSPEND o NU_SUSPEND o un valor de tiempo de espera
Devoluciones:
NU_SUCCESS - la llamada se completó con éxito
NU_INVALID_MAILBOX - el puntero del buzón no es válido
NU_INVALID_POINTER - el puntero del mensaje es NULL
NU_INVALID_SUSPEND - se intentó suspender desde un hilo que no es de tarea
NU_MAILBOX_FULL - el buzón está lleno y no se especificó la suspensión
NU_TIMEOUT - el buzón aún está lleno incluso después de suspenderlo durante el período especificado
NU_MAILBOX_DELETED - el buzón se eliminó mientras la tarea estaba suspendida
NU_MAILBOX_WAS_RESET - el buzón se reinició mientras la tarea estaba suspendida
Llamada a la API de Nucleus SE para enviar a un buzón
Esta llamada a la API admite la funcionalidad clave de la API Nucleus RTOS.
Prototipo de llamada de servicio:
STATUS NUSE_Mailbox_Send (buzón NUSE_MAILBOX, mensaje ADDR *, U8 suspender);
Parámetros:
buzón - el índice (ID) del buzón que se utilizará
mensaje - un puntero al mensaje que se va a enviar, que es una única variable de tipo ADDR
suspender - especificación para la suspensión de tareas; puede ser NUSE_NO_SUSPEND o NUSE_SUSPEND
Devoluciones:
NUSE_SUCCESS - la llamada se completó con éxito
NUSE_INVALID_MAILBOX - el índice del buzón no es válido
NUSE_INVALID_POINTER - el puntero del mensaje es NULL
NUSE_INVALID_SUSPEND - se intentó suspender desde un hilo que no es de tarea o cuando el bloqueo de llamadas a la API no estaba habilitado
NUSE_MAILBOX_FULL - el buzón está lleno y no se especificó la suspensión
NUSE_MAILBOX_WAS_RESET - el buzón se reinició mientras la tarea estaba suspendida
Implementación de Nucleus SE de Mailbox Send
La mayor parte del código de NUSE_Mailbox_Send () La función API, después de la verificación de parámetros, se selecciona mediante compilación condicional, dependiendo de si está habilitada la compatibilidad con el bloqueo (suspensión de tareas) de las llamadas a la API. Veremos las dos variantes por separado aquí.
Si el bloqueo no está habilitado, la lógica para esta llamada a la API es bastante simple y el código requiere poca explicación:
if (NUSE_Mailbox_Status [buzón]) / * buzón lleno * / {return_value =NUSE_MAILBOX_FULL;} else / * buzón vacío * / {NUSE_Mailbox_Data [buzón] =* mensaje; NUSE_Mailbox_Status [buzón] =TRUE; return_value =NUSE_SUCCESS;}
El mensaje se almacena en el elemento apropiado de NUSE_Mailbox_Data [] y el buzón marcado como en uso.
Cuando el bloqueo está habilitado, el código se vuelve más complejo:
hacer {if (! NUSE_Mailbox_Status [buzón]) / * buzón vacío * / {NUSE_Mailbox_Data [buzón] =* mensaje; NUSE_Mailbox_Status [buzón] =TRUE; if (NUSE_Mailbox_Blocking_Count [buzón]! =0) {índice U8; / * comprobar si una tarea está bloqueada * / / * en este buzón * / NUSE_Mailbox_Blocking_Count [buzón] -; for (index =0; indexAlguna explicación puede ser útil:
El código está encerrado en do… while bucle, que continúa mientras el parámetro suspender tiene el valor NUSE_SUSPEND .
Si el buzón está vacío, el mensaje proporcionado se almacena y el estado del buzón cambia para indicar que está lleno. Se comprueba si hay tareas suspendidas (en espera de recibir) en el buzón. Si hay tareas esperando, se despierta la primera. El suspender la variable está establecida en NUSE_NO_SUSPEND y la llamada a la API finaliza con NUSE_SUCCESS .
Si el buzón está lleno y suspender está configurado en NUSE_NO_SUSPEND , la llamada a la API finaliza con NUSE_MAILBOX_FULL . Si suspender se configuró en NUSE_SUSPEND , la tarea está suspendida. Al regresar (es decir, cuando se despierta la tarea), si el valor de retorno es NUSE_SUCCESS , lo que indica que la tarea se despertó porque se había leído un mensaje (a diferencia de un restablecimiento del buzón), el código vuelve a la parte superior.
La arquitectura de los sistemas de firmware basados en ARMv8 Semáforos:servicios públicos y estructuras de datos
Incrustado
- Introducción a los bloqueos de levas y cómo funcionan
- Introducción a los tornillos de ojo y cómo funcionan
- Introducción a los ojales y cómo funcionan
- Introducción al acero inoxidable y cómo se fabrica
- COVID 19 y Cloud; COVID 19 y su impacto en las empresas
- Entrada y salida básica de C#
- Semáforos:servicios públicos y estructuras de datos
- Semáforos:introducción y servicios básicos
- Grupos de indicadores de eventos:servicios públicos y estructuras de datos
- Grupos de indicadores de eventos:introducción y servicios básicos
- Colas:introducción y servicios básicos