日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

Linux-3.14.12内存管理笔记【kmalloc与kfree实现】【转】

發(fā)布時間:2025/3/20 linux 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux-3.14.12内存管理笔记【kmalloc与kfree实现】【转】 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

本文轉載自:http://blog.chinaunix.net/uid-26859697-id-5573776.html

kmalloc()是基于slab/slob/slub分配分配算法上實現(xiàn)的,不少地方將其作為slab/slob/slub分配算法的入口,實際上是略有區(qū)別的。

現(xiàn)在分析一下其實現(xiàn):

  • 【file:/include/linux/slab.h】
  • /**
  • ?*?kmalloc?-?allocate memory
  • ?*?@size:?how many bytes of memory are required.
  • ?*?@flags:?the type of memory?to?allocate.
  • ?*
  • ?*?kmalloc?is?the normal method of allocating memory
  • ?*?for?objects smaller than page size?in?the kernel.
  • ?*
  • ?*?The @flags argument may be one of:
  • ?*
  • ?*?%GFP_USER?-?Allocate memory?on?behalf of user.?May sleep.
  • ?*
  • ?*?%GFP_KERNEL?-?Allocate normal kernel ram.?May sleep.
  • ?*
  • ?*?%GFP_ATOMIC?-?Allocation will?not?sleep.?May use emergency pools.
  • ?*?For?example,?use this inside interrupt handlers.
  • ?*
  • ?*?%GFP_HIGHUSER?-?Allocate pages from high memory.
  • ?*
  • ?*?%GFP_NOIO?-?Do?not?do?any I/O at all?while?trying?to?get?memory.
  • ?*
  • ?*?%GFP_NOFS?-?Do?not?make any fs calls?while?trying?to?get?memory.
  • ?*
  • ?*?%GFP_NOWAIT?-?Allocation will?not?sleep.
  • ?*
  • ?*?%__GFP_THISNODE?-?Allocate node-local memory only.
  • ?*
  • ?*?%GFP_DMA?-?Allocation suitable?for?DMA.
  • ?*?Should only be used?for?kmalloc()?caches.?Otherwise,?use a
  • ?*?slab created with SLAB_DMA.
  • ?*
  • ?*?Also it?is?possible?to?set?different flags by?OR'ing
  • ?*?in?one?or?more of the following additional @flags:
  • ?*
  • ?*?%__GFP_COLD?-?Request cache-cold pages instead of
  • ?*?trying?to?return cache-warm pages.
  • ?*
  • ?*?%__GFP_HIGH?-?This allocation has high priority?and?may use emergency pools.
  • ?*
  • ?*?%__GFP_NOFAIL?-?Indicate that this allocation?is?in?no way allowed?to?fail
  • ?*?(think twice before using).
  • ?*
  • ?*?%__GFP_NORETRY?-?If?memory?is?not?immediately available,
  • ?*?then?give up at once.
  • ?*
  • ?*?%__GFP_NOWARN?-?If?allocation fails,?don't issue any warnings.
  • ?*
  • ?*?%__GFP_REPEAT?-?If?allocation fails initially,?try once more before failing.
  • ?*
  • ?*?There are other flags available as well,?but these are?not?intended
  • ?*?for?general use,?and?so are?not?documented here.?For?a full list of
  • ?*?potential flags,?always refer?to?linux/gfp.h.
  • ?*/
  • static __always_inline void?*kmalloc(size_t size,?gfp_t flags)
  • {
  • ????if?(__builtin_constant_p(size))?{
  • ????????if?(size?>?KMALLOC_MAX_CACHE_SIZE)
  • ????????????return kmalloc_large(size,?flags);
  • #ifndef CONFIG_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
  • ????}
  • ????return __kmalloc(size,?flags);
  • }
  • ?

    kmalloc()的參數(shù)size表示申請的空間大小,而flags則表示分配標志。kamlloc的分配標志眾多,各標志都分配標識特定的bit位,藉此可以多樣組合。

    GFP_USER:用于表示為用戶空間分配內存,可能會引起休眠;

    GFP_KERNEL:內核內存的常規(guī)分配,可能會引起休眠;

    GFP_ATOMIC:該分配不會引起休眠,但可能會使用應急內存資源,通常用于中斷處理中;

    GFP_HIGHUSER:使用高端內存進行分配;

    GFP_NOIO:分配內存時,禁止任何IO操作;

    GFP_NOFS:分配內存時,禁止任何文件系統(tǒng)操作;

    GFP_NOWAIT:分配內存時禁止休眠;

    __GFP_THISNODE:分配內存時,僅從本地節(jié)點內存中分配;

    GFP_DMA:從DMA內存中分配合適的內存,應僅使用于kmalloc的cache分配;

    __GFP_COLD:用于請求分配冷熱頁中的冷頁;

    __GFP_HIGH:用于表示該分配優(yōu)先級較高并可能會使用應急內存資源;

    __GFP_NOFAIL:用于指示該分配不允許分配失敗,該標志需要慎用;

    __GFP_NORETRY:如果分配內存未能夠直接獲取到,則不再嘗試分配,直接放棄;

    __GFP_NOWARN:如果分配過程中失敗,不上報任何告警;

    __GFP_REPEAT:如果分配過程中失敗,則嘗試再次申請;

    函數(shù)入口if判斷內的__builtin_constant_p是Gcc內建函數(shù),用于判斷一個值是否為編譯時常量,是則返回true,否則返回false。也就意味著如果調用kmalloc()傳入常量且該值大于KMALLOC_MAX_CACHE_SIZE(即申請空間超過kmalloc()所能分配最大cache的大小),那么將會通過kmalloc_large()進行分配;否則都將通過__kmalloc()進行分配。如果通過kmalloc_large()進行內存分配,將會經kmalloc_large()->kmalloc_order()->__get_free_pages(),最終通過Buddy伙伴算法申請所需內存。

    伙伴算法前面已經分析過了,不再贅述,接下來看__kmalloc()的實現(xiàn):

  • 【file:/mm/slub.c】
  • void?*__kmalloc(size_t size,?gfp_t flags)
  • {
  • ????struct kmem_cache?*s;
  • ????void?*ret;
  • ?
  • ????if?(unlikely(size?>?KMALLOC_MAX_CACHE_SIZE))
  • ????????return kmalloc_large(size,?flags);
  • ?
  • ????s?=?kmalloc_slab(size,?flags);
  • ?
  • ????if?(unlikely(ZERO_OR_NULL_PTR(s)))
  • ????????return s;
  • ?
  • ????ret?=?slab_alloc(s,?flags,?_RET_IP_);
  • ?
  • ????trace_kmalloc(_RET_IP_,?ret,?size,?s->size,?flags);
  • ?
  • ????return ret;
  • }
  • ?

    該函數(shù)同樣判斷申請是否超過最大cache大小,如果是則通過kmalloc_large()進行分配;接著通過申請大小及申請標志調用kmalloc_slab()查找適用的kmem_cache;最后通過slab_alloc()進行slab分配。

    具體看一下kmalloc_slab()的實現(xiàn):

  • 【file:/mm/slab_commmon.c】
  • /*
  • ?*?Find the kmem_cache structure that serves a given size of
  • ?*?allocation
  • ?*/
  • struct kmem_cache?*kmalloc_slab(size_t size,?gfp_t flags)
  • {
  • ????int?index;
  • ?
  • ????if?(unlikely(size?>?KMALLOC_MAX_SIZE))?{
  • ????????WARN_ON_ONCE(!(flags?&?__GFP_NOWARN));
  • ????????return?NULL;
  • ????}
  • ?
  • ????if?(size?<=?192)?{
  • ????????if?(!size)
  • ????????????return ZERO_SIZE_PTR;
  • ?
  • ????????index?=?size_index[size_index_elem(size)];
  • ????}?else
  • ????????index?=?fls(size?-?1);
  • ?
  • #ifdef CONFIG_ZONE_DMA
  • ????if?(unlikely((flags?&?GFP_DMA)))
  • ????????return kmalloc_dma_caches[index];
  • ?
  • #endif
  • ????return kmalloc_caches[index];
  • }
  • ?

    如果申請的大小超過KMALLOC_MAX_SIZE最大值,則返回NULL表示失敗;如果申請大小小于192,且不為0,將通過size_index_elem宏轉換為下標后,經size_index全局數(shù)組取得索引值,否則將直接通過fls()取得索引值;最后如果開啟了DMA內存配置且設置了GFP_DMA標志,將結合索引值通過kmalloc_dma_caches返回kmem_cache管理結構信息,否則將通過kmalloc_caches返回該結構。

    由此可以看出kmalloc()實現(xiàn)較為簡單,起分配所得的內存不僅是虛擬地址上的連續(xù)存儲空間,同時也是物理地址上的連續(xù)存儲空間。這是有別于后面將會分析到的vmalloc()申請所得的內存。

    此外再過一下kfree()的接口實現(xiàn),該函數(shù)在多處均有實現(xiàn),主要是在slab.c/slob.c/slub.c中,所以也說kmalloc()和kfree()是基于slab/slob/slub實現(xiàn)的。這里接前面的slub算法,主要分析一下slub.c中的kfree()實現(xiàn):

  • 【file:/mm/slub.c】
  • void kfree(const?void?*x)
  • {
  • ????struct page?*page;
  • ????void?*object?=?(void?*)x;
  • ?
  • ????trace_kfree(_RET_IP_,?x);
  • ?
  • ????if?(unlikely(ZERO_OR_NULL_PTR(x)))
  • ????????return;
  • ?
  • ????page?=?virt_to_head_page(x);
  • ????if?(unlikely(!PageSlab(page)))?{
  • ????????BUG_ON(!PageCompound(page));
  • ????????kfree_hook(x);
  • ????????__free_memcg_kmem_pages(page,?compound_order(page));
  • ????????return;
  • ????}
  • ????slab_free(page->slab_cache,?page,?object,?_RET_IP_);
  • }
  • ?

    該函數(shù)實現(xiàn)簡單,首先是經過trace_kfree()記錄kfree軌跡,然后if (unlikely(ZERO_OR_NULL_PTR(x)))對地址做非零判斷,接著virt_to_head_page(x)將虛擬地址轉換到頁面;再是判斷if (unlikely(!PageSlab(page)))判斷該頁面是否作為slab分配管理,如果是的話則轉為通過slab_free()進行釋放,否則將進入if分支中;在if分支中,將會kfree_hook()做釋放前kmemleak處理(該函數(shù)主要是封裝了kmemleak_free()),完了之后將會__free_memcg_kmem_pages()將頁面釋放,同時該函數(shù)內也將cgroup釋放處理。

    kmalloc()和kfree()也就這么簡單了。

    轉載于:https://www.cnblogs.com/zzb-Dream-90Time/p/9023118.html

    總結

    以上是生活随笔為你收集整理的Linux-3.14.12内存管理笔记【kmalloc与kfree实现】【转】的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。