Registro RT-Thread (8, comprender la gestión de memoria RT-Thread)

RT-Thread内核的我们已经基本都学习过了,除了基本的线程操作和通信,
内核部分还有内存管理和中断处理,本文主要就来说说内存管理相关问题。

prefacio

"Recuerdo haber aprendido RT-Thread al principio. También eché un vistazo breve a la gestión de la memoria y luego le eché un vistazo. En ese momento, sentí que no era útil. En algunos proyectos de sensor de un solo producto que hice, era realmente no importa si sé o no sobre la gestión de la memoria, pero con el reconocimiento Con el crecimiento del conocimiento, la complejidad del proyecto ha aumentado y se ha descubierto que la gestión de la memoria sigue siendo indispensable, por lo que hoy es solo para actualizar el registro RT-Thread de nuevo, y es necesario hablar de ello.

RT-Thread tiene dos métodos de administración de memoria, a saber, administración dinámica de almacenamiento dinámico de memoria y administración de grupos de memoria estática.

Independientemente de cómo se implementen estos dos métodos, primero debemos entender una pregunta, ¿por qué la gestión de la memoria?

1. Por qué la gestión de la memoria

¿Qué es la gestión de memoria? ¿Por qué necesita administración de memoria?

En el diseño de nuestro programa, el tamaño de la memoria de algunos datos debe determinarse de acuerdo con la situación real durante la ejecución del programa. Cuando el usuario necesita un cierto espacio de memoria, se aplica al sistema y el sistema selecciona un espacio de memoria adecuado para asignar al usuario, y el usuario termina de usarlo.Después de eso, se libera de nuevo al sistema para que el sistema pueda reciclar el espacio de memoria para su reutilización.

Tal aplicación y lanzamiento continuos, si no hay administración de memoria, conducirá a la fragmentación de la memoria, lo que tendrá un gran impacto en el programa.

Las razones específicas se explican en detalle en la siguiente publicación de blog:

Hablando de la aplicación de la función malloc en una microcomputadora de un solo chip

Si lee la publicación de blog anterior, debe conocer la importancia de la gestión de la memoria.

Creamos variables temporales directamente en funciones o subprocesos y usamos la pila de subprocesos o la pila del sistema para procesar variables temporales, pero como se menciona en la publicación de blog anterior, como sistema operativo general, tendrá y debe tener su propio método razonable de administración de memoria.
Esto ya está implementado por el kernel en el sistema operativo RT-Thread que estamos explicando ahora, y tenemos que entenderlo.

Sabiendo por qué, echemos un vistazo a estos dos métodos de administración de memoria de RT-Thread.

2. Gestión del montón de memoria RT-Thread

Ahora mire la gestión del montón de memoria, el llamado montón, los amigos que han leído la publicación de mi blog deberían estar muy familiarizados con él. Debe tener una comprensión detallada de la ubicación y el tamaño del montón en el metal desnudo. Si no Si no conoce el montón, puede consultar la siguiente publicación de blog para obtener una comprensión paso a paso:

Gestión de memoria relacionada con STM32 (arquitectura de memoria, gestión de memoria, análisis de archivos de mapas)

Aunque lo anterior usa STM32 como ejemplo, el orden del segmento de datos almacenado después de la compilación del programa C/C++ es básicamente el mismo en diferentes chips, por lo que está en otra publicación de mi blog.

Pila de tareas y pila de sistema de RTOS integrado

Se obtiene un diagrama esquemático de asignación de memoria:
inserte la descripción de la imagen aquí

2.1 Asignación de memoria RT-Thread

Para comprender la administración del montón de memoria de RT-Thread, primero debe saber qué parte de la memoria administra, por lo que debe conocer la asignación de memoria de RT-Thread.

De hecho, los amigos cuidadosos encontrarán que estoy en la publicación del blog.

Registro de RT-Thread (2. Proceso de inicio del kernel de RT-Thread: archivo de inicio y análisis del código fuente)

La asignación de memoria RT-Thread se menciona en el artículo y se 2.2.2 RT-Thread 堆和栈空间说明(与FreeRTOS不同)ha explicado en él:
inserte la descripción de la imagen aquíinserte la descripción de la imagen aquí

A través del análisis anterior, podemos obtener un diagrama esquemático de la asignación de memoria en RT-Thread:

inserte la descripción de la imagen aquí

A través de nuestro propio análisis anterior, combinado con la descripción de la documentación oficial, deberíamos poder comprender completamente qué es el montón de memoria RT-Thread:
inserte la descripción de la imagen aquí

En este punto, podemos entender realmente qué parte de la memoria es administrada por la administración de memoria RT-Thread.

2.2 Gestión del montón de memoria RT-Thread

Entonces, ¿cómo gestiona RT-Thread el montón de memoria?

Nota: Para esta parte, mi registro personal se basa en el conocimiento. Después de todo, nuestra columna se basa principalmente en aplicaciones. Podemos usarla si la conocemos. Si realmente necesitamos escribir la administración de memoria nosotros mismos en el futuro, definitivamente lo haremos. actualizar una publicación de blog separada.
Nuestra introducción básica anterior usa directamente las instrucciones del sitio web oficial, y la última parte de esta sección explicará cómo elegir usarlo en el próximo programa.

2.2.1 3 formas de gestión del montón de memoria

La gestión del montón de memoria RT-Thread se divide en tres situaciones según los dispositivos de memoria específicos:

  • Gestión de asignación para pequeños bloques de memoria (algoritmo de gestión de memoria pequeña)
  • Gestión de asignación para grandes bloques de memoria (algoritmo de gestión de losa)
  • Asignación de varios montones de memoria (algoritmo de gestión de memheap)

Aquí hay una breve descripción de la introducción oficial (si necesita saber más, puede ir al sitio web oficial para ver):
inserte la descripción de la imagen aquíinserte la descripción de la imagen aquíinserte la descripción de la imagen aquí

2.2.2 Configuración del programa del modo de gestión

Presentamos brevemente los tres métodos de administración de almacenamiento dinámico de memoria RT-Thread anteriores. Aunque no analizamos en detalle cómo se implementa la implementación interna, también debemos comprender cómo configurar y usar qué método de administración en el proyecto RT-Thread, y al mismo tiempo entender La implementación de estos métodos está en el archivo del programa.

En el proyecto rtconfig.h, hay una configuración sobre el método de administración de memoria:
inserte la descripción de la imagen aquí
la imagen de arriba es el uso de un pequeño algoritmo de administración de almacenamiento dinámico de memoria.

Si se utiliza el algoritmo de gestión de losas, las macros deben definirse de la siguiente manera:

#define RT_USING_SLAB
#define RT_USING_HEAP

Si usa el algoritmo de administración de memheap, debe definir la macro de la siguiente manera:

#define RT_USING_MEMHEAP_AS_HEAP

El archivo de implementación específico está en el mem.carchivo , como se muestra a continuación:
inserte la descripción de la imagen aquí

Para la implementación detallada de la gestión de memoria RT-Thread, puede ver este archivo usted mismo, por lo que no lo presentaré demasiado aquí.

2.3 Funciones de la API del montón de memoria

Para la gestión del montón de memoria RT-Thread, tiene su propia mallocfunción y no puede usar directamente la mallocfunción original en la biblioteca de lenguaje C.

Las API proporcionadas por sus tres algoritmos de gestión son las mismas.

inicialización:

La primera es la función de inicialización:

/*小内存堆和slab 管理算法*/
void rt_system_heap_init(void* begin_addr, void* end_addr);

/*memheap 管理算法*/
rt_err_t rt_memheap_init(struct rt_memheap  *memheap,
                        const char  *name,
                        void        *start_addr,
                        rt_uint32_t size)

Mencioné esta función en el resumen de "RT-Thread Record (2. Proceso de inicio del kernel de RT-Thread - Archivo de inicio y análisis de código fuente)" Inicialización de hardware a nivel de placa: rt_hw_board_init: la
inserte la descripción de la imagen aquí
función de inicialización del montón de memoria de RT-Thread se inicia el sistema comienza Se inicializa en ese momento, en lugar de que nuestros usuarios lo reinicialicen en la función principal.

Funciones de operación de gestión de memoria:

Solo una nota rapida:

/*
分配内存块
参数:
nbytes 	需要分配的内存块的大小,单位为字节
返回 	——
分配的内存块地址 	成功
RT_NULL 	失败
*/
void *rt_malloc(rt_size_t nbytes);
/*
释放内存块
参数:
ptr 	待释放的内存块指针
*/
void rt_free (void *ptr);
/*
重分配内存块
参数 	描述
rmem 	指向已分配的内存块
newsize 	重新分配的内存大小
返回 	——
重新分配的内存块地址 	成功
*/
void *rt_realloc(void *rmem, rt_size_t newsize);
/*
分配多内存块
参数 	描述
count 	内存块数量
size 	内存块容量
返回 	——
指向第一个内存块地址的指针 	成功 ,并且所有分配的内存块都被初始化成零。
RT_NULL 	分配失败
*/
void *rt_calloc(rt_size_t count, rt_size_t size);

/*
设置内存钩子函数
参数 	描述
hook 	钩子函数指针
*/
void rt_malloc_sethook(void (*hook)(void *ptr, rt_size_t size));
/*
上面函数的hook 函数接口
参数 	描述
ptr 	分配到的内存块指针
size 	分配到的内存块的大小
*/
void hook(void *ptr, rt_size_t size)/*
释放内存钩子函数
参数 	描述
hook 	钩子函数指针
*/
void rt_free_sethook(void (*hook)(void *ptr));
/*
上面函数的hook 函数接口
参数 	描述
ptr 	待释放的内存块指针
*/
void hook(void *ptr);

inserte la descripción de la imagen aquí

Después de liberar el bloque de memoria, el puntero del bloque de memoria debe borrarse; de ​​lo contrario, se convertirá en un puntero salvaje.

3. Grupo de memoria RT-Thread

El segundo método de administración de memoria de RT-Thread es el grupo de memoria. El grupo de memoria es un método de asignación de memoria utilizado para asignar una gran cantidad de pequeños bloques de memoria del mismo tamaño. Puede acelerar en gran medida la velocidad de asignación y liberación de memoria. y evitar en lo posible la fragmentación de la memoria.
Es para mejorar la eficiencia de la asignación de memoria y evitar la fragmentación de la memoria.

La introducción básica aplica la descripción oficial:
inserte la descripción de la imagen aquí

¡Los grupos de memoria son objetos del kernel! ! Función de suspensión de hilo de soporte.

¿Qué significa línea del núcleo? Como mencionamos anteriormente, los hilos, los mecanismos IPC, estas cosas son objetos del núcleo, por lo que hay un bloque de control del grupo de memoria.

¡Una cosa a tener en cuenta es que el tamaño del bloque de memoria solicitado por el grupo de memoria es fijo!

3.1 La ubicación del grupo de memoria

El grupo de memoria también es administración de memoria, entonces, ¿dónde está en la memoria después de que se crea?

En primer lugar, comprenda que el grupo de memoria, como objeto, en realidad puede considerarse como una variable, por lo que básicamente pertenece al segmento .bss En RT-Thread, su ubicación debe estar en el segmento .bss.

Sigamos el diagrama anterior de asignación de memoria para explicar la ubicación de la memoria de la aplicación del grupo de memoria:
inserte la descripción de la imagen aquí
para verificar si este es el caso, puede inicializar un grupo de memoria y verificar el archivo .map después de compilar:
inserte la descripción de la imagen aquí

El grupo de memoria pertenece a los datos en el segmento .bss, pero generalmente se aplica a un espacio de memoria relativamente grande y luego tiene su propio método de administración de asignación en este espacio grande.

3.2 Bloque de control y configuración del programa de pool de memoria

Configuración del programa del grupo de memoria:

Los archivos de configuración e implementación del grupo de memoria de RT-Thread en el programa son los siguientes:
inserte la descripción de la imagen aquí

Bloque de control del grupo de memoria: (Debido a que es un objeto interno, sigue siendo una receta familiar y un sabor familiar ~~)

struct rt_mempool
{
    
    
    struct rt_object parent;

    void        *start_address;  /* 内存池数据区域开始地址 */
    rt_size_t     size;           /* 内存池数据区域大小 */

    rt_size_t     block_size;    /* 内存块大小  */
    rt_uint8_t    *block_list;   /* 内存块列表  */

    /* 内存池数据区域中能够容纳的最大内存块数  */
    rt_size_t     block_total_count;
    /* 内存池中空闲的内存块数  */
    rt_size_t     block_free_count;
    /* 因为内存块不可用而挂起的线程列表 */
    rt_list_t     suspend_thread;
    /* 因为内存块不可用而挂起的线程数 */
    rt_size_t     suspend_thread_count;
};
typedef struct rt_mempool* rt_mp_t;

Para la implementación del método de administración específico del grupo de memoria, puede verificar el código fuente usted mismo, y no haremos una investigación en profundidad aquí por el momento.

3.3 Funciones API de operación de pool de memoria

El grupo de memoria se utiliza como un objeto del núcleo, por lo que sus operaciones son las mismas que las de los mecanismos y subprocesos de IPC anteriores, que se dividen en creación dinámica e inicialización estática.

No hay necesidad de inicializar a nivel de placa. Los usuarios pueden optar por utilizar o no.

Registre brevemente la función de operación del grupo de memoria:

/*
创建内存池
参数 	描述
name 	内存池名
block_count 	内存块数量
block_size 	内存块容量
返回 	——
内存池的句柄 	创建内存池对象成功
RT_NULL 	创建失败
*/
rt_mp_t rt_mp_create(const char* name,
                         rt_size_t block_count,
                         rt_size_t block_size);
/*
删除内存池
参数 	描述
mp 	rt_mp_create 返回的内存池对象句柄
返回 	——
RT_EOK 	删除成功
*/
rt_err_t rt_mp_delete(rt_mp_t mp);
/*
初始化内存池
参数 	描述
mp 	内存池对象
name 	内存池名
start 	内存池的起始位置
size 	内存池数据区域大小
block_size 	内存块容量
返回 	——
RT_EOK 	初始化成功
- RT_ERROR 	失败
*/
rt_err_t rt_mp_init(rt_mp_t mp,
                        const char* name,
                        void *start, rt_size_t size,
                        rt_size_t block_size);
/*
脱离内存池
参数 	描述
mp 	内存池对象
返回 	——
RT_EOK 	成功
*/
rt_err_t rt_mp_detach(rt_mp_t mp);
/*
分配内存块
参数 	描述
mp 	内存池对象
time 	超时时间
返回 	——
分配的内存块地址 	成功
RT_NULL 	失败
*/
void *rt_mp_alloc (rt_mp_t mp, rt_int32_t time);
/*
释放内存块
参数 	描述
block 	内存块指针
*/
void rt_mp_free (void *block);

Epílogo

Este artículo comienza explicando por qué se necesita la administración de memoria y comprende los dos métodos de administración de memoria de RT-Thread: montón de memoria y grupo de memoria.

Creo que no importa si suele usar la aplicación de memoria dinámica o no, después de leer este artículo, tendrá una cierta comprensión de la gestión de memoria de RT-Thread, y no se sentirá perdido cuando necesite usar la asignación de memoria dinámica en ¡el futuro!

Pero preste especial atención, sin importar qué método se use, debe liberarse a tiempo después de que se agote la memoria aplicada, ¡y preste atención a borrar el puntero correspondiente!

Sin embargo, el enfoque de este artículo es comprender por qué se necesita la administración de memoria y qué parte de la memoria se administra mediante la administración de memoria. Solo tomamos prestadas las instrucciones oficiales sobre cómo implementar la administración de memoria, y todavía no hay una investigación profunda y análisis. Esto debe esperar hasta que el bloguero tenga la oportunidad de escribir un conjunto de métodos de administración de memoria por sí mismo, y puede abrir una publicación de blog separada para un análisis en profundidad.

¡Gracias!

Supongo que te gusta

Origin blog.csdn.net/weixin_42328389/article/details/124118729
Recomendado
Clasificación