¿Cómo puedo hacer la transferencia de datos dinámicos y gestión de memoria a través de hilos en C?

StackOverflow https://stackoverflow.com/questions/689514

  •  22-08-2019
  •  | 
  •  

Pregunta

Plataforma: ARM9

Lenguaje de Programación C

Requisitos -. C plano y no hay bibliotecas externas y sin refuerzo

OS - REX RTOS

Tengo dos subprocesos que se ejecutan en una plataforma embebida -

  1. uno es en el manejo de todas las comunicaciones y transferencia de datos con el hardware de nivel de controlador.
  2. la segunda hebra se ejecuta la aplicación que utiliza los datos a / desde el hardware.

La idea es disociar el hilo aplicación desde el hilo conductor para que podamos cambiar el hardware y aplicación en el hilo conductor de hardware, pero tienen un impacto mínimo en el subproceso de la aplicación.

Mi reto es que los datos recibidos desde el hardware puede ser dinámico, es decir que no sabemos por adelantado la cantidad de memoria del subproceso de la aplicación de reservar a los cada solicitud a / desde el hardware, ya que se determina en tiempo de ejecución.

Yo estaba pensando el hilo conductor podría informar al subproceso de la aplicación que hay tantos datos a leer. El subproceso de la aplicación a continuación asigna la memoria y solicita el hilo conductor para leer los datos. Es entonces hasta el subproceso de la aplicación para procesar los datos en consecuencia. De esta manera, toda la gestión de memoria está dentro del subproceso de la aplicación.

¿Fue útil?

Solución

Opciones de los pares vienen a la mente:

1) malloc la memoria en el controlador, liberarlo en la aplicación. Pero ... que tienden a evitar el uso de malloc en todo lo que se acerca a un requisito de tiempo real. Si tiene acceso a malloc / libre, y no hay problemas de "tiempo real" o problemas de fragmentación de memoria (es decir, el montón es lo suficientemente grande), entonces este es un enfoque bastante fácil. El conductor simplemente envía el puntero asignado al hilo de aplicación a través de una cola de mensajes y la aplicación gratuita es la memoria cuando haya terminado. Tenga cuidado con los agujeros de memoria.

2) Anillo o tampones circulares. El conductor maneja por completo una memoria cíclica tamaño fijo y simplemente envía un mensaje a la aplicación cuando un buffer está listo. Vea aquí algunos detalles: circular búfer . A continuación, la aplicación marca los datos "disponibles" de nuevo a través de un controlador de API, lo que ayuda a ocultar los detalles de amortiguamiento del anillo de la rosca aplicación. Utilizamos este enfoque para uno de nuestros conductores que tiene un conjunto muy similar de los requisitos que usted describe. En este caso, tiene que estar preocupado con la determinación de la "mejor" para el tamaño de la memoria cíclica, desbordamiento de manipulación en el conductor, etc.

buena suerte!

Otros consejos

no especifica un sistema operativo, pero que de alguna manera tienen "hilos". Excepto que uno de ellos es a nivel de controlador (controlador de interrupción) y los otros sonidos como una aplicación (espacio de usuario / kernel). Pero eso no se corresponde tampoco, debido a que su conductor y aplicación se comunican antes de que la técnica ha sido aún procesado.

Su terminología es confusa y no es alentador. Es este un sistema operativo homebrew (RT) o no?

Si usted tiene un sistema operativo real, hay métodos para la escritura de los conductores y los datos entregando al espacio de usuario establecida. Lea la documentación o utilizar uno de los controladores existentes como referencia.

Si se trata de un sistema operativo a medida, todavía se puede hacer referencia a otros controladores de código abierto para las ideas, pero que claramente no tendrá cosas establecido como convenientemente. Asignar previamente toda la memoria en el código del controlador, llenarlo con los datos a medida que llega, y la mano de apagado al código de la aplicación. La cantidad de memoria será una función de la velocidad de su aplicación puede procesar los datos, la mayor cantidad de datos que va a aceptar, y cómo se necesita mucho colas de datos interna para apoyar su aplicación.

Este ser C, he terminado por tener que hacer la aplicación se registra una devolución de llamada con el conductor. El propósito de la devolución de llamada es para procesar los datos después de que el conductor lo lee desde el dispositivo. El controlador gestiona la memoria la memoria es decir, asigna, invoca la devolución de llamada y finalmente libera memoria. Además, sólo la devolución de llamada tiene permiso de lectura en la memoria. Por lo tanto, la aplicación, lo ideal sería simplemente copiar el contenido del búfer a su propia memoria y la salida de la devolución de llamada de inmediato. Entonces es libre para procesar los datos cuando y cómo se desea.

He actualizado la documentación para que quede claro a los usos de la devolución de llamada aplicación que se supone que los rendimientos de devolución de llamada, la memoria ya no deberían ser consideradas válidas. Si la devolución de llamada se utiliza de otra manera, el comportamiento es indefinido.

Lo primero que pensé sería el uso de buffer circular. Aquí es un código de ejemplo. Siéntase libre de adaptar esto a sus propios usos. Es probable que no quiere que las variables globales. Y puede que no desee #defines:

#define LENGTH (1024)
#define MASK (LENGTH-1)
uint8 circularBuffer[ LENGTH ];
int circularBuffer_add = 0;
int circularBuffer_rmv = 0;

void copyIn( uint8 * circularBuffer, uint8 * inputBuffer, int n ) {
    int i;
    for( i = 0; i < n; i++ ) {
        circularBuffer[ circularBuffer_add ] = inputBuffer[ i ];
        circularBuffer_add = ( circularBuffer_add + 1 ) & MASK;
    } 
}

void copyOut( uint8 * circularBuffer, uint8 * outputBuffer, int n ) {
    int i;
    for( i = 0; i < n; i++ ) {
        outputBuffer[ i ] = circularBuffer[ circularBuffer_rmv ];
        circularBuffer_rmv = ( circularBuffer_rmv + 1 ) & MASK;
    } 
}

También el código anterior supone que su unidad de datos es el tipo de datos "uint8". Puede cambiarlo para que utilice algún otro tipo de datos. O incluso se puede hacer que sea genérico y uso memcpy () para copiar en el buffer circular.

La característica principal de este código es cómo se maneja el complemento y PTR RMV.


Una vez que las cosas que trabajan con el código de seguridad. Sugiero en algún punto de conmutación durante toda la lee desde el hardware a utilizar su plataforma de directo memoria- acceso API .

importante para cambiar a-memoria de acceso directo, ya que el código anterior utiliza una gran cantidad de ciclos en relación con DMA que utiliza casi cero ciclos.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top