kmallocとvmallocの違い



Difference Between Kmalloc



Kmallocはvmallocとは完全に異なります。

kmalloc

Kmallocは、物理アドレスと論理アドレスの連続したメモリ空間に適用されます。



/* Apply for a contiguous memory space of a physical address */ static __always_inline void *kmalloc(size_t size, gfp_t flags) { if (__builtin_constant_p(size)) { If (size > KMALLOC_MAX_CACHE_SIZE) //The application space is greater than one page_size return kmalloc_large(size, flags) #ifndef CONFIG_SLOB /* In the case of configuring slob: the application space is less than one page_size: allocated from kmalloc_caches in the slob */ if (!(flags & GFP_DMA)) { int index = kmalloc_index(size) if (!index) return ZERO_SIZE_PTR return kmem_cache_alloc_trace(kmalloc_caches[index], flags, size) } #endif } /* In case of no slob configured: the application space is less than one page_size: allocated from kmalloc_caches in slab */ return __kmalloc(size, flags) }

メモリサイズ> PAGE_SIZEを適用すると、ページはパートナーシステムから割り当てられます
サイズ

kmalloc_cachesの具体的な設定は次のとおりです。



struct kmem_cache *kmalloc_caches[KMALLOC_SHIFT_HIGH + 1] EXPORT_SYMBOL(kmalloc_caches)

vmalloc

Vmallocは、連続する論理アドレスと不連続な物理アドレスを持つメモリ空間を要求します。

/** Apply for a contiguous section of virtual address memory (physical address is not continuous, different from malloc) In fact, apply for a number of pages, so that the size of the N*page is greater than or equal to the size * vmalloc - allocate virtually contiguous memory * @size: allocation size * Allocate enough pages to cover @size from the page level * allocator and map them into contiguous kernel virtual space. * * For tight control over page level allocator and protection flags * use __vmalloc() instead. */ void *vmalloc(unsigned long size) return __vmalloc_node_flags(size, NUMA_NO_NODE, GFP_KERNEL static inline void *__vmalloc_node_flags(unsigned long size, int node, gfp_t flags) { return __vmalloc_node(size, 1, flags, PAGE_KERNEL, node, __builtin_return_address(0)) } static void *__vmalloc_node(unsigned long size, unsigned long align, gfp_t gfp_mask, pgprot_t prot, int node, const void *caller) { return __vmalloc_node_range(size, align, VMALLOC_START, VMALLOC_END, gfp_mask, prot, 0, node, caller) } void *__vmalloc_node_range(unsigned long size, unsigned long align, unsigned long start, unsigned long end, gfp_t gfp_mask, pgprot_t prot, unsigned long vm_flags, int node, const void *caller) (size >> PAGE_SHIFT) > totalram_pages) goto fail area = __get_vm_area_node(size, align, VM_ALLOC / / Enter the __vmalloc_area_node function inside static void *__vmalloc_area_node(struct vm_struct *area, gfp_t gfp_mask, pgprot_t prot, int node) { const int order = 0 struct page **pages unsigned int nr_pages, array_size, i const gfp_t nested_gfp = (gfp_mask & GFP_RECLAIM_MASK) | __GFP_ZERO const gfp_t alloc_mask = gfp_mask | __GFP_NOWARN nr_pages = get_vm_area_size(area) >> PAGE_SHIFT array_size = (nr_pages * sizeof(struct page *)) area->nr_pages = nr_pages /* Please note that the recursion is strictly bounded. */ / / Apply for a continuous space for the pages array if (array_size > PAGE_SIZE) __GFP_HIGHMEM, PAGE_KERNEL, node, area->caller) else { pages = kmalloc_node(array_size, nested_gfp, node) } area->pages = pages if (!area->pages) { remove_vm_area(area->addr) kfree(area) return NULL } for (i = 0 i nr_pages i++) { struct page *page if (node == NUMA_NO_NODE) //alloc_page requests a single page page = alloc_kmem_pages(alloc_mask, order) else page = alloc_kmem_pages_node(node, alloc_mask, order) if (unlikely(!page)) { /* Successfully allocated i pages, free them in __vunmap() */ area->nr_pages = i goto fail } area->pages[i] = page if (gfpflags_allow_blocking(gfp_mask)) cond_resched() } / / Modify the page table entry used by the kernel, establish the mapping of the logical address of the vmalloc area to the physical address of the page if (map_vm_area(area, prot, pages)) goto fail return area->addr fail: warn_alloc_failed(gfp_mask, order, 'vmalloc: allocation failure, allocated %ld of %ld bytes ', (area->nr_pages*PAGE_SIZE), area->size) vfree(area->addr) return NULL }

Map_vm_areaを使用して、カーネルが使用するページテーブルエントリを変更し、vmalloc領域の論理アドレスからページの物理アドレスへのマッピングを確立する必要があります。