Memory management of embedded systems

C language defines 5 storage classes for variables, namely automatic (auto), register (register), static with external link (extern), static with internal link (static in file), static with code block scope ( code block static) . Different storage classes determine the scope and storage period.

So what is the relationship between storage classes and memory?

From the perspective of storage period, it is divided into static, automatic and allocation.

Static storage (static) has been determined at compile time and exists during the entire program runtime; variables (auto, register) are generated when the code block is running and are cleared when exiting; dynamic memory allocation is generated when malloc or related functions are called, and is released when free . Because allocation and deallocation are not linear, this results in memory fragmentation.

The scope determines which part of the program can access which data.

In embedded systems, memory exists in the form of heap and stack. The stack is automatically allocated and released by the system, and the heap is allocated and released by the developer.

In the data structure scenario, heap and stack represent two commonly used data structures.

Heap memory management

The declaration of memory allocation in C language is in stdlib.h. There are four main functions:

malloc

calloc

realloc

free

No matter which function applies for memory, it must be released using free after completion. Of course, if it is a system like Linux, after allocating memory, the program will be executed while it is running, even if it is not free. When the process terminates, the memory it occupies will be returned to the operating system. You can see a lot of sample code that does this.

Regarding the management of heap memory, different embedded platforms and different operating systems have certain differences.

  • In a bare metal environment, especially the platform represented by stm32 bit, the keil compiler used implements a simplified version of the C standard library, called the MicroLIB library. For allocation of large blocks of memory, it is recommended to use a global array and avoid applying and releasing multiple times.
  • There is already basic memory management in ucos. Use the interface functions provided by ucos to apply for and release heap memory.
  • Memory management in Linux is quite complete. Generally, global data can be used. If it is a large memory block (such as 128KB or more), it is usually mapped through the mmap system call. After use, ummap releases the memory.

Generally, embedded systems are divided as follows:

  1. Stack: It is automatically allocated and released by the compiler to store function parameter values, local variable values, return addresses, etc. Its operation method is similar to the stack in the data structure.
  2. Heap: It is generally dynamically allocated (calling the mallo0 function) and released (calling the free0 function) by the programmer. If the programmer does not release it, it may be recycled by the operating system when the program ends.
  3. Data segment (data): stores global variables, static variables, and constants. According to the stored data, the data segment can be divided into ordinary data segment (including readable and writable/read-only data segment, which stores static initialized global variables or constants) and BSS data segment (which stores uninitialized global variables).
  4. Code segment (code): used to store program code.

So generally what is dynamically applied for is heap memory. When malloc is used to allocate memory, a few additional bytes will be allocated to store and record the memory size. The memory allocated by malloc needs to be initialized, usually using memset. Calloc will initialize the allocated memory to 0.

Unix systems also provide alloca to allocate memory, but instead of applying from the heap, the second is to allocate from the stack by increasing the size of the stack frame. There is no need for free to release memory.

Linux memory management

Linux's memory management is built on the MMU (Memory Management Unit), which is used to implement virtual memory management between the CPU and memory. Its main function is to convert virtual addresses into physical addresses, while providing access control and cache management functions.

In terms of memory management, MMU can implement virtual memory management through page tables (Page Table). The page table is a data structure that records the mapping relationship between each virtual page and its corresponding physical page. When the CPU issues a virtual address, the MMU looks it up through the page table and converts it to the corresponding physical address.

Linux uses virtual memory management technology, using virtual memory technology to allow each process to have a 4GB virtual address space that does not interfere with each other.

The initial allocation and operation of the process are based on this "virtual address". Only when the process needs to actually access memory resources will the mapping between the virtual address and the physical address be established and the physical memory page be transferred.

Benefits of virtual addresses

  • Prevent users from directly accessing physical memory addresses, prevent some destructive operations, and protect the operating system.
  • Each process is allocated 4GB of virtual memory, and user programs can use a larger address space than the actual physical memory.

4GB The process virtual address space is divided into two parts: 3GB user space + 1GB kernel space.

在Linux系统malloc Used to apply for virtual memory in user space. When applying for  128KB memory smaller than small, mallocuse  sbrk或brk allocated memory; when applying for  128KB memory larger than small, use  mmap function to apply for memory;

Guess you like

Origin blog.csdn.net/huntenganwei/article/details/131457986