九色国产,午夜在线视频,新黄色网址,九九色综合,天天做夜夜做久久做狠狠,天天躁夜夜躁狠狠躁2021a,久久不卡一区二区三区

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費(fèi)電子書(shū)等14項(xiàng)超值服

開(kāi)通VIP
linux內(nèi)存管理

Linux內(nèi)核學(xué)習(xí)筆記九——內(nèi)核內(nèi)存管理方式

一 頁(yè)

       內(nèi)核把物理頁(yè)作為內(nèi)存管理的基本單位;內(nèi)存管理單元(MMU)把虛擬地址轉(zhuǎn)換為物理

地址,通常以頁(yè)為單位進(jìn)行處理。MMU以頁(yè)大小為單位來(lái)管理系統(tǒng)中的也表。

       32位系統(tǒng):頁(yè)大小4KB

       64位系統(tǒng):頁(yè)大小8KB

內(nèi)核用相應(yīng)的數(shù)據(jù)結(jié)構(gòu)表示系統(tǒng)中的每個(gè)物理頁(yè):

  <linux/mm_types.h>

  struct page {}

內(nèi)核通過(guò)這樣的數(shù)據(jù)結(jié)構(gòu)管理系統(tǒng)中所有的頁(yè),因此內(nèi)核判斷一個(gè)頁(yè)是否空閑,誰(shuí)有擁有這個(gè)頁(yè)

,擁有者可能是:用戶空間進(jìn)程、動(dòng)態(tài)分配的內(nèi)核數(shù)據(jù)、靜態(tài)內(nèi)核代碼、頁(yè)高速緩存……

系統(tǒng)中每一個(gè)物理頁(yè)都要分配這樣一個(gè)結(jié)構(gòu)體,進(jìn)行內(nèi)存管理。

二 區(qū)

       Linux內(nèi)存尋址存在問(wèn)題:

一些硬件只能用某些特定的內(nèi)存來(lái)執(zhí)行DMA(直接內(nèi)存訪問(wèn))

一些體系結(jié)構(gòu)其內(nèi)存的物理尋址范圍必須你尋址范圍大得多。這樣導(dǎo)致一些內(nèi)存不能永久映射到內(nèi)核空間上。

       通常32位Linux內(nèi)核地址空間劃分0~3G為用戶空間,3~4G為內(nèi)核空間。當(dāng)內(nèi)核模塊代碼或線程訪問(wèn)內(nèi)存時(shí),

代碼中的內(nèi)存地址都為邏輯地址,而對(duì)應(yīng)到真正的物理內(nèi)存地址,需要地址一對(duì)一的映射。因此內(nèi)核空間地址為3~4G,

最多只能映射到1G空間的內(nèi)存,超出1G大小的內(nèi)存將如何去問(wèn)呢!

       由于存在上述條件的限制。Linux將內(nèi)核空間地址劃分為三個(gè)區(qū):

ZONE_DMA、ZONE_NORMAL和ZONE_HIGHMEM。

       ZONE_HIGHMEM即為高端內(nèi)存,這就是內(nèi)存高端內(nèi)存概念的由來(lái)。

 

在x86結(jié)構(gòu)中,三種類(lèi)型的區(qū)域如下:

  ZONE_DMA        內(nèi)存開(kāi)始的16MB

  ZONE_NORMAL       16MB~896MB

  ZONE_HIGHMEM       896MB ~ 結(jié)束

同樣每個(gè)區(qū)包含眾多頁(yè),形成不同內(nèi)存池,按照用途進(jìn)行內(nèi)存分配。

用相應(yīng)的數(shù)據(jù)結(jié)構(gòu)來(lái)表示區(qū):

  <linux/mmzone.h>

  struct zone {}

三 獲取頁(yè)/內(nèi)存

static inline struct page *alloc_pages(gfp_t gfp_mask, unsigned int order)

該函數(shù)分配2的order次方個(gè)連續(xù)的物理頁(yè),返回指向第一個(gè)頁(yè)的page結(jié)構(gòu)體指針。

 

void *page_address(const struct page *page)

返回指向給定物理頁(yè)當(dāng)前所在的邏輯地址

extern unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order);

extern unsigned long get_zeroed_page(gfp_t gfp_mask);

釋放:

extern void __free_pages(struct page *page, unsigned int order);

extern void free_pages(unsigned long addr, unsigned int order);

 

內(nèi)存的分配可能失敗,內(nèi)存的釋放要準(zhǔn)確!

 

1 kmalloc

kmalloc()函數(shù)與用戶空間malloc一組函數(shù)類(lèi)似,獲得以字節(jié)為單位的一塊內(nèi)核內(nèi)存。

void *kmalloc(size_t size, gfp_t flags)

void kfree(const void *objp)

 

分配內(nèi)存物理上連續(xù)。

gfp_t標(biāo)志:表明分配內(nèi)存的方式。如:

GFP_ATOMIC:分配內(nèi)存優(yōu)先級(jí)高,不會(huì)睡眠

GFP_KERNEL:常用的方式,可能會(huì)阻塞。

 

2 vmalloc    

 

void *vmalloc(unsigned long size)

void vfree(const void *addr)

vmalloc()與kmalloc方式類(lèi)似,vmalloc分配的內(nèi)存虛擬地址是連續(xù)的,而物理地址則無(wú)需連續(xù),與用戶空間分配函數(shù)一致。

vmalloc通過(guò)分配非連續(xù)的物理內(nèi)存塊,在修正頁(yè)表,把內(nèi)存映射到邏輯地址空間的連續(xù)區(qū)域中,虛擬地址是連續(xù)的。

       是否必須要連續(xù)的物理地址和具體使用場(chǎng)景有關(guān)。在不理解虛擬地址的硬件設(shè)備中,內(nèi)存區(qū)都必須是連續(xù)的。

       通過(guò)建立頁(yè)表轉(zhuǎn)換成虛擬地址空間上連續(xù),肯定存在一些消耗,帶來(lái)性能上影響。

所以通常內(nèi)核使用kmalloc來(lái)申請(qǐng)內(nèi)存,在需要大塊內(nèi)存時(shí)使用vmalloc來(lái)分配。

 

四 slab層

       內(nèi)核中經(jīng)常進(jìn)行內(nèi)存的分配和釋放。為了便于數(shù)據(jù)的頻繁分配和回收,通常建立一個(gè)空

 

閑鏈表——內(nèi)存池。當(dāng)不使用的已分配的內(nèi)存時(shí),將其放入內(nèi)存池中,而不是直接釋放掉。

       Linux內(nèi)核提供了slab層來(lái)管理內(nèi)存的分配和釋放。

頻繁分配和回收必然導(dǎo)致內(nèi)存碎片,緩存他們.

slab層得設(shè)計(jì)實(shí)現(xiàn)

       slab層把不同的對(duì)象劃分為所謂的高速緩存組。每個(gè)高速緩存組存放不同類(lèi)型的對(duì)象。高速緩存劃分為slab,

slab由一個(gè)或多個(gè)物理上連續(xù)的頁(yè)組成。每個(gè)slab處于三種狀態(tài)之一:滿,部分滿,空。

高速緩存,slab,對(duì)象之間的關(guān)系:

     

 

 

       與傳統(tǒng)的內(nèi)存管理模式相比, slab 緩存分配器提供了很多優(yōu)點(diǎn)。首先,內(nèi)核通常依賴(lài)于對(duì)小對(duì)象的分配,

它們會(huì)在系統(tǒng)生命周期內(nèi)進(jìn)行無(wú)數(shù)次分配。slab 緩存分配器通過(guò)對(duì)類(lèi)似大小的對(duì)象進(jìn)行緩存而提供這種功能,

從而避免了常見(jiàn)的碎片問(wèn)題。slab 分配器還支持通用對(duì)象的初始化,從而避免了為同一目而對(duì)一個(gè)對(duì)象重復(fù)

進(jìn)行初始化。最后,slab 分配器還可以支持硬件緩存對(duì)齊和著色,這允許不同緩存中的對(duì)象占用相同的緩存行,

從而提高緩存的利用率并獲得更好的性能。

 

slab數(shù)據(jù)結(jié)構(gòu)和接口:

每個(gè)高速緩存用kmem_cache結(jié)構(gòu)來(lái)表示:

       struct kmem_cache {

              struct kmem_list3 **nodelists;

              ……

       }

緩存區(qū)包含三種slab:滿,未滿,空閑

struct kmem_list3 {

       struct list_head slabs_partial; /* partial list first, better asm code */

       struct list_head slabs_full;

       struct list_head slabs_free;

       ……

};

每一個(gè)slab包含多個(gè)對(duì)象:

struct slab {

              struct list_head list;

              unsigned long colouroff;

              void *s_mem;            /* including colour offset */

              unsigned int inuse;     /* num of objs active in slab */

              kmem_bufctl_t free;

              unsigned short nodeid;

};

 

相關(guān)接口:mm/slab.c

              內(nèi)核函數(shù) kmem_cache_create 用來(lái)創(chuàng)建一個(gè)新緩存。這通常是在內(nèi)核初始化時(shí)執(zhí)行的,或者在首次加載內(nèi)核模塊時(shí)執(zhí)行。

struct kmem_cache *kmem_cache_create (

  const char *name,

  size_t size,

  size_t align,

  unsigned long flags,

  void (*ctor)(void *))

      

name 參數(shù)定義了緩存名稱(chēng),proc 文件系統(tǒng)(在 /proc/slabinfo 中)使用它標(biāo)識(shí)這個(gè)緩存。

size 參數(shù)指定了為這個(gè)緩存創(chuàng)建的對(duì)象的大小,

align 參數(shù)定義了每個(gè)對(duì)象必需的對(duì)齊。

flags 參數(shù)指定了為緩存啟用的選項(xiàng):

  kmem_cache_create 的部分選項(xiàng)(在 flags 參數(shù)中指定)

  SLAB_RED_ZONE    在對(duì)象頭、尾插入標(biāo)志,用來(lái)支持對(duì)緩沖區(qū)溢出的檢查。

  SLAB_POISON  使用一種己知模式填充 slab,允許對(duì)緩存中的對(duì)象進(jìn)行監(jiān)視(對(duì)象屬對(duì)象所有,不過(guò)可以在外部進(jìn)行修改)。

  SLAB_HWCACHE_ALIGN      指定緩存對(duì)象必須與硬件緩存行對(duì)齊。

ctor 和 dtor 參數(shù)定義了一個(gè)可選的對(duì)象構(gòu)造器和析構(gòu)器。構(gòu)造器和析構(gòu)器是用戶提供的回調(diào)函數(shù)。當(dāng)從緩存中分配新對(duì)象時(shí),可以通過(guò)構(gòu)造器進(jìn)行初始化。

    要從一個(gè)命名的緩存中分配一個(gè)對(duì)象,可以使用 kmem_cache_alloc 函數(shù)。

 

void kmem_cache_alloc( struct kmem_cache *cachep, gfp_t flags );

這個(gè)函數(shù)從緩存中返回一個(gè)對(duì)象。注意如果緩存目前為空,那么這個(gè)函數(shù)就會(huì)調(diào)用 cache_alloc_refill 向緩存中增加內(nèi)存。

kmem_cache_alloc 的 flags 選項(xiàng)與 kmalloc 的

cachep:所建立的緩存區(qū)

flags參數(shù):

  GFP_USER 為用戶分配內(nèi)存(這個(gè)調(diào)用可能會(huì)睡眠)。

  GFP_KERNEL    從內(nèi)核 RAM 中分配內(nèi)存(這個(gè)調(diào)用可能會(huì)睡眠)。

  GFP_ATOMIC   使該調(diào)用強(qiáng)制處于非睡眠狀態(tài)(對(duì)中斷處理程序非常有用)。

  GFP_HIGHUSER      從高端內(nèi)存中分配內(nèi)存。

 

五 高端內(nèi)存的映射

永久映射:可能會(huì)阻塞

  映射一個(gè)給定的page結(jié)構(gòu)到內(nèi)核地址空間:

  void *kmap(struct page *page)

  解除映射:

  void kunmap(struct page *page)

 

臨時(shí)映射:不會(huì)阻塞     

void *kmap_atomic(struct page *page)

 

六 分配函數(shù)的選擇

  l  連續(xù)的物理頁(yè):kmalloc或者低級(jí)頁(yè)分配器

  l  高端內(nèi)存分配:alloc_pages 指向page結(jié)構(gòu)指針,不是邏輯地址指針。再通過(guò)kmap()把高端地址內(nèi)存映射到內(nèi)核的邏輯地址空間。

  l  無(wú)需連續(xù)物理地址:vmalloc 虛擬地址連續(xù)物理地址可能不連續(xù),相對(duì)存在性能損失

  l  頻繁創(chuàng)建和銷(xiāo)毀很多較大數(shù)據(jù)結(jié)構(gòu):建立slab緩存區(qū),提高對(duì)象分配和回收性能。

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
工程師深度:學(xué)通Linux內(nèi)核(含詳細(xì)代碼)
SLAB
linux內(nèi)核分析筆記----內(nèi)存管理
Linux slab
linux 3.4.10 內(nèi)核內(nèi)存管理源代碼分析10:slab通用長(zhǎng)度內(nèi)存分配
Linux內(nèi)存管理之SLAB分配器
更多類(lèi)似文章 >>
生活服務(wù)
熱點(diǎn)新聞
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服