transferred from: http://blog.csdn.net/myarrow/article/details/86828191. First Fit Splitter
The first fit allocator is the most basic memory allocator, which uses bitmap instead of a free block list to represent memory. In bitmap, if the page corresponds to a bit of 1, the page is already assigned, and 0 indicates that the page is not assigned. In order to allocate a block of memory less than one page, the first fit allocator records the last assigned PFN (page Frame number) and the offset of the assigned ending address within the page. The small memory allocations are then merge together and stored on the same page.
The first fit allocator does not cause significant memory fragmentation, but it is less efficient because memory is often search through a linear address, and the small chunks of memory in initial fit often have to be scanned for large amounts of memory in order to allocate large chunks of memory at the beginning of physical memory.
2. Boot Memory Splitter
How does the physical memory allocator allocate memory to initialize itself?
The answer is: The boot memory allocator is implemented, and the boot memory allocator is implemented by the most basic first fit allocator.
2.1 Boot Map Definition
The Boot map is defined by the data structure Bootmem_data, as described in <linux/bootmem.h>, which is defined as follows:
[CPP]View Plaincopy
- typedef struct Bootmem_data {
- unsigned long node_boot_start; //Description of the starting address of the physical memory
- unsigned long node_low_pfn; //End physical address, i.e. end of Zone_normal
- void *node_bootmem_map; //Describe the address of "used or free bitmap"
- unsigned long last_offset; //The last assigned page offset, which is the physical page described in Llast_pos,
- //Starting from Last_offset, not assigned
- unsigned long last_pos; //PFN of the last assigned page
- } bootmem_data_t;
All bootmem_data are placed in the global variable bdata_list.
2.2 Boot Memory Allocator initialization
Each CPU architecture is required to provide the Setup_arch function, which is responsible for obtaining the necessary parameters for initializing the boot memory allocator. Different CPU architectures are implemented by different functions, such as arm through Bootmem_init. It is responsible for obtaining the following parameters:
MIN_LOW_PFN: The smallest PFN available in the system, loaded kernel the first page after the end of the image, defined in MM/BOOTMEM.C
MAX_LOW_PFN: Maximum PFN available in low-end memory (zone_normal)
HIGHSTART_PFN: Start of high-end memory (ZONE_HIGHMEM) PFN
HIGHEND_PFN: End of high-end memory (ZONE_HIGHMEM) PFN
MAX_PFN: The largest PFN available in the system, defined in MM/BOOTMEM.C
PFN is the offset in the physical memory map, in page units. The kernel has direct access to the zone_normal with an offset of: Page_offset.
After defining the available physical memory with the above 5 parameters, call Init_bootmem->init_bootmem_core to initialize the contig_page_data. It mainly accomplishes the following two things:
1) Insert the corresponding pgdat_data_t with this node into the Pgdat_list
2) Initialize the bootmem_data_t parameter and assign a bitmap that represents the page assignment state, with the size: (END_PFN-START_PFN+7)/8
The physical address of the bitmap is: Bootmem_data_t->node_boot_start
Bitmap's Virtual ground is: Bootmem_data_t->node_bootmem_map
2.3 Allocating memory
Reserve_bootmem: Used to reserve physical pages. However, the memory allocation used for general purpose is low, it is mainly used for various drives (such as Video Codec) reserved memory.
The usual memory allocation functions are as follows (in the UMA architecture, our usual arm architecture is the UMA architecture):
Alloc_bootmem
Alloc_bootmem_low
alloc_bootmem_pages
alloc_bootmem_low_pages
Its invocation relationship is as follows:
2.3.1 __alloc_bootmem
__alloc_bootmem () requires the following parameters:
Pgdat
The node used to allocate memory blocks in the UMA schema, which is ignored because it is always: contig_page_data
size
Specifies the size, in bytes, of the requested allocated memory
Align
How many bytes are requested to be aligned to a small chunk of memory allocation, generally smp_cache_bytes aligned, as on X86, aligned with the L1 hardware CACHE
goal
The starting address of the preferred allocated memory,
2.3.2 __alloc_bootmem_core
It scans the memory linearly, starting at the address specified by goal, to find a block of memory that can meet the memory allocation requirements. Another function of this is to decide whether to merge the newly allocated blocks of memory with the previously allocated blocks of memory.
Common functions for allocating memory are defined as follows:
[CPP]View Plaincopy
- #ifdef CONFIG_NO_BOOTMEM
- /* We are using the top down, so it's safe to use 0 here */
- #define BOOTMEM_LOW_LIMIT 0
- #else
- #define BOOTMEM_LOW_LIMIT __PA (max_dma_address)
- #endif
- #define ALLOC_BOOTMEM (x) \
- __alloc_bootmem (x, Smp_cache_bytes, Bootmem_low_limit)
- #define ALLOC_BOOTMEM_ALIGN (x, align) \
- __alloc_bootmem (x, Align, bootmem_low_limit)
- #define ALLOC_BOOTMEM_NOPANIC (x) \
- __alloc_bootmem_nopanic (x, Smp_cache_bytes, Bootmem_low_limit)
- #define ALLOC_BOOTMEM_PAGES (x) \
- __alloc_bootmem (x, Page_size, Bootmem_low_limit)
- #define ALLOC_BOOTMEM_PAGES_NOPANIC (x) \
- __alloc_bootmem_nopanic (x, Page_size, Bootmem_low_limit)
- #define ALLOC_BOOTMEM_NODE (pgdat, x) \
- __alloc_bootmem_node (Pgdat, X, Smp_cache_bytes, Bootmem_low_limit)
- #define ALLOC_BOOTMEM_NODE_NOPANIC (pgdat, x) \
- __alloc_bootmem_node_nopanic (Pgdat, X, Smp_cache_bytes, Bootmem_low_limit)
- #define ALLOC_BOOTMEM_PAGES_NODE (pgdat, x) \
- __alloc_bootmem_node (Pgdat, X, Page_size, Bootmem_low_limit)
- #define ALLOC_BOOTMEM_PAGES_NODE_NOPANIC (pgdat, x) \
- __alloc_bootmem_node_nopanic (Pgdat, X, Page_size, Bootmem_low_limit)
- #define ALLOC_BOOTMEM_LOW (x) \
- __alloc_bootmem_low (x, smp_cache_bytes, 0)
- #define ALLOC_BOOTMEM_LOW_PAGES (x) \
- __alloc_bootmem_low (x, page_size, 0)
- #define ALLOC_BOOTMEM_LOW_PAGES_NODE (pgdat, x) \
- __alloc_bootmem_low_node (Pgdat, X, page_size, 0)
2.4 Freeing up memory
Call Free_bootmem to free memory.
[CPP]View Plaincopy
- void __init Free_bootmem (unsigned long addr, unsigned long size)
- {
- Unsigned long start, end;
- Kmemleak_free_part (__va (addr), size);
- Start = pfn_up (addr);
- End = Pfn_down (addr + size);
- Mark_bootmem (start, end, 0, 0);
- }
Linux Memory Management-Physical memory allocation "Go"