複習 linux記憶體管理

2021-10-04 15:39:45 字數 3665 閱讀 6970

頁(page)是核心的記憶體管理基本單位。

/*  linux/mm_types.h */

struct page

;

儘管處理器的最小可定址單位通常為字或位元組,但記憶體管理單元(mmu,把虛擬位址轉換為實體地址的硬體裝置)通常以頁為單位處理。核心用struct page結構體表示每個物理頁,struct page結構體占40個位元組,假定系統物理頁大小為4kb,對於4gb物理記憶體,1m個頁面,故所有的頁面page結構體共占有記憶體大小為40mb,相對系統4g,這個代價並不高。

核心把頁劃分在不同的區(zone),總共3個區,具體如下:區描述

物理記憶體(mb)

zone_dma

dma使用的頁

<16

zone_normal

可正常定址的頁

16 ~896

zone_highmem

動態對映的頁

>896

執行dma操作的記憶體必須從zone_dma區分配,

一般記憶體,既可從zone_dma,也可從zone_normal分配,但不能同時從兩個區分配;

頁分配函式

描述alloc_pages(gfp_mask, order)

分配2^order個頁,返回指向第一頁的指標

alloc_pages(gfp_mask)

分配一頁,返回指向頁的指標

__get_free_pages(gfp_mask, order)

分配2^order個頁,返回指向其邏輯位址的指標

__get_free_pages(gfp_mask)

分配一頁,返回指向其邏輯位址的指標

get_zeroed_page(gfp_mask)

分配一頁,並填充內容為0,返回指向其邏輯位址的指標

get_zeroed_page:對於使用者空間,這個方法能保障系統敏感資料不會洩露

頁釋放函式

描述__free_pages(page, order)

從page開始,釋放2^order個頁

free_pages(addr, order)

從位址addr開始,釋放2^order個頁

free_page(addr)

釋放addr所在的那一頁

kmalloc,vmalloc分配都是以位元組為單位

kmalloc

該函式返回的是乙個指向記憶體塊的指標,其記憶體塊大小至少為size,所分配的內存在物理記憶體中連續且保持原有的資料(不清零)

void * kmalloc(size_t size, gfp_t flags)

其中部分flags取值說明:

kzalloc

kzalloc()等價於先用 kmalloc() 申請空間, 再用memset()來初始化,所有申請的元素都被初始化為0。

static

inline

void

*kzalloc

(size_t size, gfp_t flags)

vmalloc

該函式返回的是乙個指向記憶體塊的指標,其記憶體塊大小至少為size,所分配的記憶體是邏輯上連續的。與kmalloc不同,該函式沒有flag,預設是可以休眠的。

void * vmalloc(unsigned long size)

小結:分配函式

區域連續性

大小釋放函式

優勢kmalloc

核心空間

實體地址連續

最大值128k-16

kfree

效能更佳

vmalloc

核心空間

虛擬位址連續

更大vfree

更易分配大記憶體

malloc

使用者空間

虛擬位址連續

更大free

分配和釋放資料結構是所有核心中最普遍的操作之一,為了便於資料的頻繁分配和**,程式設計者常常會用到乙個空閒鍊錶,該空閒鍊錶包含有可供使用的、已經分配好的資料結構塊,當**需要乙個新的資料結構例項時,就可以從空閒鍊錶中抓取乙個,而不需要分配記憶體,在把資料放進去。當不需要這個資料結構的例項時,在將它放回空閒鍊錶,而不是釋放它。於是linux核心提供了slab層(也就是所謂的slab分配器)。扮演了通用資料結構快取層的角色。

設計原則::

每個快取記憶體又被劃分為slab,slab由乙個或多個物理上連續的頁組成,一般僅僅由一頁組成,每個快取記憶體可以由多個slab組成。每個slab都包含一些物件成員,這裡物件指的是被快取的資料結構,每個slab處於三種狀態之一:滿、部分滿或空。當核心的某一部分需要乙個新的物件時,先從部分滿的slab中進行分配(滿的表示物件全部分配出去)。如果沒有部分滿的slab,就從空的slab中進行分配。如果沒有空的slab就建立乙個slab。這種策略能減少碎片。示例圖如下:

每個快取記憶體都是用kmem_cache_s結構來表示。這個結構包含三個鍊錶slabs_full、slabs_partial和slabs_empty,均存放在kmem_list3結構內。這些鍊錶包含快取記憶體中的所有slab。

slab分配器的介面;

例項分析: 核心初始化期間,/kernel/fork.c的fork_init()中會建立乙個名叫task_struct的快取記憶體; 每當程序呼叫fork()時,會通過dup_task_struct()建立乙個新的程序描述符,並呼叫do_fork(),完成從快取記憶體中獲取物件。

當設定單頁核心棧,那麼每個程序的核心棧只有一頁大小,這取決於編譯時配置選項。 好處:

若機器安裝的物理記憶體超過核心位址空間範圍,就會存在高階記憶體。

32位系統使用者程序最大可以訪問3gb,核心**可以訪問所有物理記憶體(得益於高階記憶體)。

核心將高階記憶體劃分為3部分:

對應高階記憶體的3部分,高階記憶體對映有三種方式:

小結:

kunmap:持久對映的數量有限,應通過kunmap及時解除對映

kmap_atomic: 臨時對映

kunmap_atomic: 解除臨時對映

問:為什麼核心空間與使用者空間做1:3的劃分?

答:減少使用者態與核心切換時的開銷。對於任何使用者程序,0-3g的對映都是不同的,但是所有使用者程序3-4g的對映都是相同的。乙個程序從使用者態切入到核心態(系統呼叫或者中斷),mmu對映不需要變。你能很方便取得核心資料和使用者程序的資料。

反證,如果核心空間和使用者空間都是0~4g範圍的話,當核心空間被使用者空間替換時,還有誰能把使用者空間切換成核心空間?(因為管理記憶體的角色不正是核心嗎!)

分配函式選擇:

記憶體區域可包含的物件:

/* */

struct mm_struct

;

mm_count: 代表mm_struct的主引用計數,當該值為0說明沒有任何指向該mm_struct結構體的引用,結構體會被撤銷。

mmap和mm_rb:描述的物件都是相同的

mmap以鍊錶形式存放, 利於高效地遍歷所有元素

mm_rb以紅黑樹形式存放,適合搜尋指定元素

linux C複習 記憶體管理

1 虛擬記憶體位址 每個程序都有4g的虛擬記憶體位址,當程序需要真正的物理空間時,向系統申請,系統會分配給程序相應的物理記憶體空間。系統會將程序的一部分虛擬記憶體位址和分配好的物理記憶體之間一 一對應起來,這個過程叫記憶體對映。2 產生段錯誤的原因 1 當程式訪問或修改沒有許可權訪問或修改的記憶體空...

記憶體管理簡便複習總結

在virtual的知識裡摸爬滾打好幾天,最近大腦有些不夠用了,現在整理一下 非考慮記憶體對齊時各個結構的大致模型 至於考綠記憶體的在前面幾張已經敘述過了,為了方便,我再紙上畫了整體的流程,記憶體分配要注意對齊引數 min pack,最大位元組的型別 虛函式指標和虛函式表指標跨越的大小一定是對齊引數的...

記憶體管理簡便複習總結

在virtual的知識裡摸爬滾打好幾天,最近大腦有些不夠用了,現在整理一下 非考慮記憶體對齊時各個結構的大致模型 至於考綠記憶體的在前面幾張已經敘述過了,為了方便,我再紙上畫了整體的流程,記憶體分配要注意對齊引數 min pack,最大位元組的型別 虛函式指標和虛函式表指標跨越的大小一定是對齊引數的...