¿Realloc desperdicia mucho espacio en mi MCU?

4

Estoy escribiendo un programador de tareas simple y utilizando la asignación de memoria dinámica en mi cc430F5137. Estoy de acuerdo en que no es una buena práctica, pero por el momento, asumamos que es un requisito de mi aplicación utilizar la asignación de memoria dinámica.

En mi archivo OS.c

Tengo dos estructuras,

typedef struct
{
    task_t task;
    uint8_t next;
    uint8_t prev;
    uint8_t priority;

} info_t;


typedef struct
{
    task_t task;
    uint8_t index;
} index_t;

el tamaño de info_t es de 8 bytes y el tamaño de index_t es de 6 bytes.

También lo hago

index_t* m_index;
info_t* m_info;

Luego tengo la función de inicializar en la que hago

m_info = NULL;
m_index = NULL;

Ahora tengo una función registerTask(& task) que toma la dirección de la función para programar. En esta función hago

m_info = realloc(m_info,(num_registered_tasks + 1) * sizeof(*m_info));

y luego establezca los valores de .priority, next, task y prev.

Entonces lo hago

m_index = realloc(m_index,(num_registered_tasks + 1) * sizeof(*m_index));

y establezca los valores de tarea e índice.  y hacer num_registered_tasks++;

Mi pregunta es cómo se está comportando realloc() a este respecto.

Supongamos que mi espacio de memoria, La primera tarea está registrada, por lo que tendrá los primeros 8 bytes para m_info[0] y los siguientes 6 bytes para m_index[0] . Ahora cuando mi segunda tarea llama a esta función, ¿qué pasará? Lo que supongo es que para m_info primero buscará 16 bytes de datos continuos y solo los encontrará después de los primeros 14 bytes, cambiará la dirección de m_info[0] y copiará el contenido y luego agregará m_info[1] . Y cuando se llame a m_index , solo encontrará 12 bytes después de este (14 + 16) bytes y colocará m_index[0] y m_index[1] aquí.

Si esto es cierto, ¿se está desperdiciando todo mi espacio anterior?

Si estoy equivocado, ¿cómo funcionará esta función?

¿Cómo puedo utilizar el espacio anterior también?

Necesito index_t struct para implementar algún tipo de algoritmo de búsqueda, por lo que también es necesario

    
pregunta Hassan

3 respuestas

0

Después de muchos y muchos comentarios y respuestas de no usar la memoria dinámica, todavía encontré una manera que en el momento estaba resolviendo mi problema.

Cambié esto en mi código

typedef struct
{
    task_t task;
    uint8_t next;
    uint8_t prev;
    uint8_t priority;

} info_t;


typedef struct
{
    task_t task;
    uint8_t index;
} index_t;

typedef struct
{
    info_t m_info;
    info_t m_index;
} combined_t;

combined_t* m_combined;

Por esto, nw my realloc () asigna memoria contigua a m_combined y mi problema de fragmentación se resuelve. (Bueno, supongo que después de analizar la memoria paso a paso).

    
respondido por el Hassan
21

El uso de la asignación de memoria dinámica en una MCU de 16 bits con 4kb de RAM es una ingeniería muy deficiente.

No tanto por los problemas habituales con las fugas de memoria. No tanto debido a la fragmentación de la memoria del montón. Ni siquiera debido a la sobrecarga de tiempo de ejecución bastante pronunciada necesaria para las rutinas de asignación. Pero porque es completamente inútil y no tiene sentido.

Tiene algunos requisitos del mundo real que indican lo que su programa debe hacer, y en base a estos, su programa necesitará usar exactamente x bytes de RAM para manejar el peor escenario . No necesitará menos, no necesitará más, necesitará la cantidad exacta de RAM, que puede determinarse en el momento de la compilación.

No tiene sentido guardar parte del 4kb, dejándolos sin usar. ¿Quién los va a utilizar? Del mismo modo, no tiene sentido asignar más memoria de la necesaria para el peor escenario. Simplemente asigne estáticamente tanta memoria como sea necesario, punto.

Además, tiene el peor de los casos con el uso máximo de pila, en el que se encuentra en una pila de llamadas y se han activado todas las interrupciones que están habilitadas. Este peor escenario puede calcularse en tiempo de compilación o medirse en tiempo de ejecución. Una buena práctica es asignar más RAM de la que se necesita para el peor de los casos, para evitar el desbordamiento de la pila (la pila también es un área de memoria dinámica). O más bien: use cada byte de RAM que no utilice su programa para la pila.

Si su aplicación necesita exactamente 3kb de RAM, entonces debe usar el 1kb restante para la pila.

Asignación dinámica / el montón de computadora está diseñado para usarse en aplicaciones hospedadas como Windows o Linux, donde cada proceso tiene una cantidad fija de RAM, y además puede usar la memoria del montón para usar tanta RAM como hay en la hardware. Solo tiene sentido utilizar la asignación dinámica en sistemas tan complejos y de múltiples procesos, con grandes cantidades de RAM disponibles.

En un programa de MCU, ya sea basado en metal o basado en RTOS, debe darse cuenta de que las implementaciones del montón funcionan de la siguiente manera: reserve una cantidad fija, x kb de RAM para el montón. Cuando se utiliza la asignación dinámica, se le entrega una parte de esta cantidad fija de memoria. Entonces, ¿por qué no simplemente tomar esos x kb que usaría para asignar el montón y en su lugar usarlos para almacenar sus variables?

    
respondido por el Lundin
10

Esto se llama fragmentación de la memoria.

Hay todo tipo de algoritmos sofisticados para lidiar con eso, pero la sobrecarga de contabilidad hace que sean inadecuados para una pequeña MCU.

En cambio, puede escribir sus propias rutinas de asignación de memoria según su patrón de uso esperado. Es posible que tenga una rutina separada para cada subproceso de ejecución, por ejemplo. Si puede garantizar que free () ocurra en el orden opuesto a alloc (), puede usar un puntero simple al final de la memoria.

O puede usar un nivel de direccionamiento indirecto: acceda a la memoria solo a través de un puntero a un puntero. Luego, puede recolectar libremente la memoria y ajustar la tabla del puntero para que apunte a la memoria donde sea que termine.

La mejor respuesta para los sistemas integrados suele ser evitar por completo la asignación dinámica de memoria.

    
respondido por el markrages

Lea otras preguntas en las etiquetas