This chapter focuses on the memory management of the Linux kernel.
- Inside of the Kmalloc function
- Incorrect acquisition of memory space zeroing
- The allocated area is also contiguous in physical memory
- Flags, number of references
- <linux/slab.h>
- <linux/gfp.h>
- Gfp_kernel
- Put the current process into hibernation while spare 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 executes outside the process context and does not hibernate
- Gfp_user
- Used to allocate memory for user space pages. May be dormant
- Gfp_highuser
- Like Gfp_user, it's just a fake high-end memory that's allocated from there.
- Gfp_noio, Gfp_nofs
- __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 a "cold" page that has not yet been used, and the page allocation for DMA reads. You can use this flag
- __gfp_nowarn
- Very little use. Prevents the kernel from generating a warning when an allocation request cannot be met
- __gfp_high
- Flag a high-priority request that agrees to consume the last few pages reserved by the kernel for emergency goodness
- __gfp_repeat, __gfp_nofail, __gfp_noretry
- Tells the allocator what behavior to take when it encounters difficulties in meeting the allocation request
- __gfp_repeat says "Try again" and it will try to allocate again. But it's still possible to fail.
- The __gfp_nofail flag tells the allocator to never return a failure. It will try to meet the allocation request and not be encouraged to use 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 can be used by peripherals to run DMA access
- High-end memory is a mechanism that 32-bit platforms exist to access large amounts of memory
- Assume that a specific flag is not specified. The kmalloc will be searched in the regular section and DMA section
- Assume that the __gfp_highhem flag is set. Then all three sections will be searched
- The mechanism behind the memory section is implemented in MM/PAGE_ALLOC.C
- Size number of references
- Fallback Fast Cache
- Tuning cache management for the Linux kernel is sometimes referred to as the "slab allocator"
- The fast 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 control how to complete the assignment
- Slab_no_reap
- The ability to protect fast caches is not degraded when the system is looking for memory
- Slab_hwcache_align
- All data objects are required to be aligned with the cache line. The actual operation relies on the hardware of the main platform to adjust the cache layout
- Slab_cache_dma
- Requires that each data object be allocated from a memory segment that can be used for DMA
- Mm/slab.c
- Be able to use the same function at the same time as constructor and destructor, 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);
- Fast Cache usage statistics can be obtained from/proc/slabinfo
- Memory pool
- The memory pool is actually some form of fallback cache, which attempts to always save spare memory 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 will allocate some memory blocks, spare and will not really get 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 in the inner region. But not clear 0 pages
- Parameter order is the base 2 logarithm of the number of pages to be requested or released
- 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);
The
- Vmalloc can obtain an address in the range Vmalloc_start to Vmalloc_end. Both of these symbols are defined in <asm/pgtable.h>
- the correct place to use the Vmalloc function is when allocating a large contiguous chunk of memory that exists only in the software for buffering purposes
- Ioremap Many other uses for mapping (physical) PCI buffer addresses to (virtual) kernel space
- per-cpu variable
- when a per-cpu variable is created. Each processor in the system will have a unique copy of the variable
- does not need to be locked
- can be saved in a fast cache of the appropriate processor
- <linux/percpu.h>
- DEFI NE_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 number with the _low suffix, the allocated memory may be high-end memory
The eighth chapter of Linux Device Drivers allocates memory--note