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

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
Linux內(nèi)存管理(三)_菜鳥學(xué)習(xí)筆記

內(nèi)核內(nèi)存使用

Slab

    所謂尺有所長,寸有所短。以頁為最小單位分配內(nèi)存對于內(nèi)核管理系統(tǒng)中的物理內(nèi)存來說的確比較方便,但內(nèi)核自身最常使用的內(nèi)存卻往往是很?。ㄟh遠小于一頁)的內(nèi)存塊——比如存放文件描述符、進程描述符、虛擬內(nèi)存區(qū)域描述符等行為所需的內(nèi)存都不足一頁。這些用來存放描述符的內(nèi)存相比頁面而言,就好比是面包屑與面包。一個整頁中可以聚集多個這些小塊內(nèi)存;而且這些小塊內(nèi)存塊也和面包屑一樣頻繁地生成/銷毀。

為了滿足內(nèi)核對這種小內(nèi)存塊的需要,Linux系統(tǒng)采用了一種被稱為slab分配器的技術(shù)。Slab分配器的實現(xiàn)相當(dāng)復(fù)雜,但原理不難,其核心思想就是“存儲池[4]的運用。內(nèi)存片段(小塊內(nèi)存)被看作對象,當(dāng)被使用完后,并不直接釋放而是被緩存到“存儲池”里,留做下次使用,這無疑避免了頻繁創(chuàng)建與銷毀對象所帶來的額外負載。

Slab技術(shù)不但避免了內(nèi)存內(nèi)部分片(下文將解釋)帶來的不便(引入Slab分配器的主要目的是為了減少對伙伴系統(tǒng)分配算法的調(diào)用次數(shù)——頻繁分配和回收必然會導(dǎo)致內(nèi)存碎片——難以找到大塊連續(xù)的可用內(nèi)存,而且可以很好地利用硬件緩存提高訪問速度。

   Slab并非是脫離伙伴關(guān)系而獨立存在的一種內(nèi)存分配方式,slab仍然是建立在頁面基礎(chǔ)之上,換句話說,Slab將頁面(來自于伙伴關(guān)系管理的空閑頁面鏈表)撕碎成眾多小內(nèi)存塊以供分配,slab中的對象分配和銷毀使用kmem_cache_allockmem_cache_free。

Kmalloc

Slab分配器不僅僅只用來存放內(nèi)核專用的結(jié)構(gòu)體,它還被用來處理內(nèi)核對小塊內(nèi)存的請求。當(dāng)然鑒于Slab分配器的特點,一般來說內(nèi)核程序中對小于一頁的小塊內(nèi)存的請求才通過Slab分配器提供的接口Kmalloc來完成(雖然它可分配32 131072字節(jié)的內(nèi)存)。從內(nèi)核內(nèi)存分配的角度來講,kmalloc可被看成是get_free_pages)的一個有效補充,內(nèi)存分配粒度更靈活了。

有興趣的話,可以到/proc/slabinfo中找到內(nèi)核執(zhí)行現(xiàn)場使用的各種slab信息統(tǒng)計,其中你會看到系統(tǒng)中所有slab的使用信息。從信息中可以看到系統(tǒng)中除了專用結(jié)構(gòu)體使用的slab外,還存在大量為Kmalloc而準(zhǔn)備的Slab(其中有些為dma準(zhǔn)備的)。

內(nèi)核非連續(xù)內(nèi)存分配(Vmalloc

伙伴關(guān)系也好、slab技術(shù)也好,從內(nèi)存管理理論角度而言目的基本是一致的,它們都是為了防止“分片”,不過分片又分為外部分片和內(nèi)部分片之說,所謂內(nèi)部分片是說系統(tǒng)為了滿足一小段內(nèi)存區(qū)(連續(xù))的需要,不得不分配了一大區(qū)域連續(xù)內(nèi)存給它,從而造成了空間浪費;外部分片是指系統(tǒng)雖有足夠的內(nèi)存,但卻是分散的碎片,無法滿足對大塊“連續(xù)內(nèi)存”的需求。無論何種分片都是系統(tǒng)有效利用內(nèi)存的障礙。slab分配器使得一個頁面內(nèi)包含的眾多小塊內(nèi)存可獨立被分配使用,避免了內(nèi)部分片,節(jié)約了空閑內(nèi)存?;锇殛P(guān)系把內(nèi)存塊按大小分組管理,一定程度上減輕了外部分片的危害,因為頁框分配不在盲目,而是按照大小依次有序進行,不過伙伴關(guān)系只是減輕了外部分片,但并未徹底消除。你自己比劃一下多次分配頁面后,空閑內(nèi)存的剩余情況吧。

所以避免外部分片的最終思路還是落到了如何利用不連續(xù)的內(nèi)存塊組合成“看起來很大的內(nèi)存塊”——這里的情況很類似于用戶空間分配虛擬內(nèi)存,內(nèi)存邏輯上連續(xù),其實映射到并不一定連續(xù)的物理內(nèi)存上。Linux內(nèi)核借用了這個技術(shù),允許內(nèi)核程序在內(nèi)核地址空間中分配虛擬地址,同樣也利用頁表(內(nèi)核頁表)將虛擬地址映射到分散的內(nèi)存頁上。以此完美地解決了內(nèi)核內(nèi)存使用中的外部分片問題。內(nèi)核提供vmalloc函數(shù)分配內(nèi)核虛擬內(nèi)存,該函數(shù)不同于kmalloc,它可以分配較Kmalloc大得多的內(nèi)存空間(可遠大于128K,但必須是頁大小的倍數(shù)),但相比Kmalloc來說,Vmalloc需要對內(nèi)核虛擬地址進行重映射,必須更新內(nèi)核頁表,因此分配效率上要低一些(用空間換時間)

與用戶進程相似,內(nèi)核也有一個名為init_mmmm_strcut結(jié)構(gòu)來描述內(nèi)核地址空間,其中頁表項pdg=swapper_pg_dir包含了系統(tǒng)內(nèi)核空間(3G-4G)的映射關(guān)系。因此vmalloc分配內(nèi)核虛擬地址必須更新內(nèi)核頁表,而kmallocget_free_page由于分配的連續(xù)內(nèi)存,所以不需要更新內(nèi)核頁表。

  

vmalloc分配的內(nèi)核虛擬內(nèi)存與kmalloc/get_free_page分配的內(nèi)核虛擬內(nèi)存位于不同的區(qū)間,不會重疊。因為內(nèi)核虛擬空間被分區(qū)管理,各司其職。進程空間地址分布從0到3G(其實是到PAGE_OFFSET, 0x86中它等于0xC0000000),從3Gvmalloc_start這段地址是物理內(nèi)存映射區(qū)域(該區(qū)域中包含了內(nèi)核鏡像、物理頁面表mem_map等等)比如我使用的系統(tǒng)內(nèi)存是64M(可以用free看到),那么(3G——3G+64M)這片內(nèi)存就應(yīng)該映射到物理內(nèi)存,而vmalloc_start位置應(yīng)在3G+64M附近(說"附近"因為是在物理內(nèi)存映射區(qū)與vmalloc_start期間還會存在一個8M大小的gap來防止躍界),vmalloc_end的位置接近4G(說"接近"是因為最后位置系統(tǒng)會保留一片128k大小的區(qū)域用于專用頁面映射,還有可能會有高端內(nèi)存映射區(qū),這些都是細節(jié),這里我們不做糾纏)。

上圖是內(nèi)存分布的模糊輪廓

  get_free_pageKmalloc函數(shù)所分配的連續(xù)內(nèi)存都陷于物理映射區(qū)域,所以它們返回的內(nèi)核虛擬地址和實際物理地址僅僅是相差一個偏移量(PAGE_OFFSET),你可以很方便的將其轉(zhuǎn)化為物理內(nèi)存地址,同時內(nèi)核也提供了virt_to_phys()函數(shù)將內(nèi)核虛擬空間中的物理映射區(qū)地址轉(zhuǎn)化為物理地址。要知道,物理內(nèi)存映射區(qū)中的地址與內(nèi)核頁表是有序?qū)?yīng)的,系統(tǒng)中的每個物理頁面都可以找到它對應(yīng)的內(nèi)核虛擬地址(在物理內(nèi)存映射區(qū)中的)。

vmalloc分配的地址則限于vmalloc_startvmalloc_end之間。每一塊vmalloc分配的內(nèi)核虛擬內(nèi)存都對應(yīng)一個vm_struct結(jié)構(gòu)體(可別和vm_area_struct搞混,那可是進程虛擬內(nèi)存區(qū)域的結(jié)構(gòu)),不同的內(nèi)核虛擬地址被4k大小的空閑區(qū)間隔,以防止越界——見下圖)。與進程虛擬地址的特性一樣,這些虛擬地址與物理內(nèi)存沒有簡單的位移關(guān)系,必須通過內(nèi)核頁表才可轉(zhuǎn)換為物理地址或物理頁。它們有可能尚未被映射,在發(fā)生缺頁時才真正分配物理頁面。

這里給出一個小程序幫助大家認清上面幾種分配函數(shù)所對應(yīng)的區(qū)域。

#include<linux/module.h>

#include<linux/slab.h>

#include<linux/vmalloc.h>

unsigned char *pagemem;

unsigned char *kmallocmem;

unsigned char *vmallocmem;

int init_module(void)

{

pagemem = get_free_page(0);

printk("<1>pagemem=%s",pagemem);

kmallocmem = kmalloc(100,0);

printk("<1>kmallocmem=%s",kmallocmem);

vmallocmem = vmalloc(1000000);

printk("<1>vmallocmem=%s",vmallocmem);

}

void cleanup_module(void)

{

free_page(pagemem);

kfree(kmallocmem);

vfree(vmallocmem);

}

本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
LINUX內(nèi)核內(nèi)存管理kmalloc,vmalloc
Linux內(nèi)存管理 下
內(nèi)存觀點
Linux內(nèi)存管理
Linux物理內(nèi)存管理概述
Linux內(nèi)核--內(nèi)核地址空間分布和進程地址空間
更多類似文章 >>
生活服務(wù)
熱點新聞
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服