This chapter focuses on the memory management of the Linux kernel.
- Inside of the Kmalloc function
- Do not clear the acquired memory space
- The allocated area is also contiguous in physical memory
- Flags parameter
- <linux/slab.h>
- <linux/gfp.h>
- Gfp_kernel
- Put the current process into hibernation while idle memory is low to wait for a page
- The function that allocates memory must be reentrant
- Gfp_atomic
- Used to allocate memory in interrupt-processing routines or other code that runs outside the process context and does not hibernate
- Gfp_user
- Used to allocate memory for user space pages and may hibernate
- Gfp_highuser
- Similar to Gfp_user, but if you have high-end memory, allocate it from there.
- Gfp_noio, Gfp_nofs
- The features of these two flags are similar to Gfp_kernel, but add some restrictions to how the kernel allocates memory. Allocations with the GFP_NOFS flag do not allow any file system calls to be performed, while Gfp_noio suppresses any initialization of I/O. These two flags are primarily used in file system and virtual memory code, where memory allocations can hibernate, but recursive file system calls should not occur
- __gfp_dma
- The flag request assignment occurs in a DMA-able memory segment
- __gfp_highhem
- This flag indicates that the memory to be allocated can be located in high-end memory
- __gfp_cold
- This flag requests the unused "cold" page, which can be used for DMA-read page assignments.
- __gfp_nowarn
- Rarely used to prevent the kernel from generating a warning when an allocation request cannot be met
- __gfp_high
- Flags a high-priority request that allows the last few pages reserved by the kernel to be consumed for emergency goodness
- __gfp_repeat, __gfp_nofail, __gfp_noretry
- Tells the allocator what to do if it encounters difficulties in meeting the allocation request
- __gfp_repeat says "Try again" and it will try to allocate again, but it may still fail
- The __gfp_nofail flag tells the allocator to never return a failure, it tries to satisfy the allocation request, and does not encourage the use of this flag
- __gfp_noretry tells the allocator that if the requested memory is not available, it returns immediately
- Memory section
- The use of __GFP_DMA and __gfp_highhem is platform-dependent
- The Linux kernel divides memory into three segments: memory for DMA, conventional memory, and high-end memory
- Memory available for DMA refers to memory that exists in a special address range that the peripheral can use to perform DMA access
- High-end memory is a mechanism that 32-bit platforms exist to access large amounts of memory
- If a specific flag is not specified, Kmalloc will search in the General section and DMA section
- If the __gfp_highhem flag is set, all three sections will be searched
- The mechanism behind the memory section is implemented in MM/PAGE_ALLOC.C
- Size parameter
- Linux handles memory allocations by creating a series of memory object pools in which the size of the memory blocks in each pool is consistent. When processing an allocation request, a whole block is passed directly to the requestor in a pool that contains a large enough block of memory
- The smallest memory block that Kmalloc can handle is 32 or 64.
- If you want your code to have full portability, you should not allocate more than 128KB of memory
- Backup cache
- Tuning cache management for the Linux kernel is sometimes referred to as the "slab allocator"
- The cache implemented by the slag allocator has a kmem_cache_t type
- kmem_cache_t *kem_cache_create (const char *name, size_t size, size_t offset, unsigned long flags, Void (*constructor) (Voi D *, keme_cache_t *, unsigned long flags), Void (*destructor) (void *, kmem_cache_t *, unsigned long flags));
- Parameter flags controls how allocations are completed
- Slab_no_reap
- Can protect the cache from being reduced when the system is looking for memory
- Slab_hwcache_align
- Requires all data objects to be aligned with the cache line, and the actual operation relies on the hardware-adjusted cache layout of the primary platform
- Slab_cache_dma
- Requires that each data object be allocated from a memory segment that can be used for DMA
- Mm/slab.c
- You can use the same function as both constructor and destructor, and when a constructor function is called, the slab allocator always passes the SLAB_CTOR_CONSTRUCTOR flag
- void *kmem_cache_alloc (kmem_cache_t *cache, int flags);
- void Kmem_cache_free (kmem_cache_t *cache, const void *obj);
- int Kmem_cache_destroy (kmem_cache_t *cache);
- Caching usage statistics can be obtained from/proc/slabinfo
- Memory pool
- A memory pool is actually some form of fallback cache that tries to keep free memory at all times in order to use it in a state of emergency
- The type of the memory pool object is mempool_t
- <linux/mempool.h>
- mempool_t *mempool_create (int min_nr, mempool_alloc_t *alloc_fn, mempool_free_t *free_fn, void *pool_data);
- typedef void * (mempool_alloc_t) (int gfp_mask, void *pool_data);
- typedef void (mempool_free_t) (void *element, void *pool_data);
- void *mempool_alloc (mempool_t *pool, int gfp_mask);
- void Mempool_free (void *element, mempool_t *pool);
- int Mempool_resize (mempool_t *pool, int new_min_nr, int gfp_mask);
- void Mempool_destroy (mempool_t *pool);
- Example
- cache = Kmem_cache_create (...);
- Pool =-mempool_create (My_pool_minimum, Mempool_alloc_slab, Mempool_free_slab, cache);
- Mempool allocates some memory blocks that are idle and not actually used
- You should try to avoid using Mempool in driver code
- Get_free_page and related functions
- Get_zeroed_page (unsigned int flags);
- Returns a pointer to a new page and zeroing the page
- __get_free_page (unsigned int flags);
- Similar to Get_zeroed_page, but not clear 0 pages
- __get_free_pages (unsigned int flags, unsigned int order);
- Allocates several (physically contiguous) pages and returns a pointer to the first byte of the inner region, but not 0 pages
- The parameter order is the base 2 logarithm of the number of pages to be requested or freed
- void Free_page (unsigned long addr);
- void Free_pages (unsigned long addr, unsigned long order);
- Alloc_pages interface
- struct page *alloc_pages_node (int nid, unsigned int flags, unsigned int order);
- Nid is the ID number of the NUMA node
- struct page *alloc_page (unsigned int flags, unsigned int order);
- struct page *alloc_page (unsigned int flags);
- void __free_page (struct page *page);
- void __free_pages (struct page *page, unsigned int order);
- void free_hot_page (struct page *page);
- void free_code_page (struct page *page);
- Subtopic 7
- Vmalloc and its auxiliary functions
- allocates contiguous areas of the virtual address space, which may be physically discontinuous on the right, but the kernel thinks they are contiguous on the address
- vmalloc The memory used is not efficient
- & L t;linux/vmalloc.h>
- void *vmalloc (unsigned long size);
- void Vfree (void *addr);
- void *ioremap (unsigned long offset, unsigned long size);
- void Iounmap (void *addr);
- Vmalloc can get addresses in the range Vmalloc_start to Vmalloc_end, both of which are defined in <asm/pgtable.h>
- The correct scenario for using the VMALLOC function is to allocate a chunk of contiguous, software-only memory areas for buffering,
- ioremap more for Mapping (physical) PCI buffer addresses to (virtual) kernel space
- per-cpu variable
- when a PER-CPU variable is established, each processor in the system will have a unique copy of the variable
- do not need to be locked
- can be saved in the corresponding processor cache
- & L T;linux/percpu.h>
- define_per_cpu (type, name);
- get_cpu_var (variable);
- put_cpu_var (variable);
- per_cpu (variable, int cpu_id);
- void *alloc_percpu (type);
- void *__alloc_percpu (size_t size, size_t align);
- per_cpu_ptr (void *per_cpu_var, int cpu_id);
- Export_per_cpu_symbol (Per_cpu_var);
- EXPORT_PER_CPU_SYMBOL_GPL (Per_cpu_var);
- declare_per_cpu (type, name);
- Get a large buffer
- Obtaining a private buffer at boot time
- <linux/bootmem.h>
- void *alloc_bootmem (unsigned long size);
- void *alloc_bootmem_low (unsigned long size);
- void *alloc_bootmem_pages (unsigned long size);
- void *alloc_bootmem_low_pages (unsigned long size);
- void Free_bootmem (unsigned long addr, unsigned long size);
- These functions either assign an entire page or allocate memory areas that are not aligned on the page boundary
- Unless you use a version with the _low suffix, the allocated memory may be high-end memory
The eighth chapter of Linux Device Drivers allocates memory--note