Linux 核心學習 4 記憶體管理

2021-10-13 03:04:07 字數 4492 閱讀 2541

注:以下** 有的是linux 5.10,有的是linux 2.6.30.4

**1 arch/x86/boot/memory.c

static

void

detect_memory_e820

(void

)*desc++

= buf;

count++;}

while

(ireg.ebx && count <

array_size

(boot_params.e820_table));

// 直到取出的ebx為0

boot_params.e820_entries = count;

}

**2 e820 entry定義 /usr/include/x86_64-linux-gnu/asm/bootparam.h

struct boot_e820_entry 

__attribute__

((packed)

);

**3 列印e820圖 arch/x86/kernel/e820.c

void __init e820_print_map

(char

*who)

}

用於啟動階段的乙個簡單的分配器,它負責page alloc初始化之前的記憶體分配管理以及在系統boot階段滿足最大記憶體的請求(請求大小超過page alloc的最大限制)

實現:所有狀態都儲存在乙個全域性變數中

**5 新增記憶體區域 mm/memblock.c

/**

* memblock_add_range - add new memblock region

* @type: memblock type to add new region into

* @base: base address of the new region

* @size: size of the new region

* @nid: nid of the new region

* @flags: flags of the new region

* * add new memblock region [@base, @base + @size) into @type. the new region

* is allowed to overlap with existing ones - overlaps don't affect already

* existing regions. @type is guaranteed to be minimal (all neighbouring

* compatible regions are merged) after the addition.

* * return:

* 0 on success, -errno on failure.

*/static

int __init_memblock memblock_add_range

(struct memblock_type *type,

phys_addr_t base, phys_addr_t size,

int nid,

enum memblock_flags flags)

repeat:

/* * the following is executed twice. once with %false @insert and

* then with %true. the first counts the number of regions needed

* to accommodate the new area. the second actually inserts them.

*/base = obase;

nr_new =0;

for_each_memblock_type

(idx, type, rgn)

/* area below @rend is dealt with, forget about it */

base =

min(rend, end);}

/* insert the remaining portion */

if(base < end)if(

!nr_new)

return0;

/* * if this was the first round, resize array and repeat for actual

* insertions; otherwise, merge and return.

*/if(

!insert)

else

}

**6 memblock分配記憶體

static

void

* __init memblock_alloc_internal

( phys_addr_t size, phys_addr_t align,

phys_addr_t min_addr, phys_addr_t max_addr,

int nid, bool exact_nid)

zone order:即zone的查詢次序,它決定如果當前請求的型別不滿足後應該隨後要到哪個zone中去分配。比如,使用者可能想請求zone_high,但zone_high中的記憶體已經分配完了,這時候可以讓它到其它的zone

kernel中有兩種型別的order

kernel中每乙個頁面都有乙個表示結構,即struct page,存放在struct page mem_map中,它以物理頁面的序號作為索引,每個頁面只能屬於zone,函式page_zone(page)可以找到page的zone

基於 page migration type 的頁面分組:

linux kernel為了加速單個頁面分配釋放同時又提高cache利用率而匯入的快取

位於:include/linux/mmzone.h

x86背景

cpu模式不同,定址方式上有些小差別

如果對映有異常,cpu會產生page fault異常

tlb介紹

兩大空間: 核心空間和使用者空間

核心空間和使用者空間復用一部分位址空間

將對映層次抽象成pgd, pud, pmd, pte,如果某層不存在,則其對應位數為0

各種api

kmap的apis:

kmap_atomic的apis:

slab簡而言之,就是乙個物件的快取器,當有物件釋放的時候,就快取到slab裡面,然後需要分配的時候,就從slab快取中取出來

slab以page allocator作為後端,當快取物件不夠時,就從page allocator中取

api除此之外,slab還內建了一些slab cache, 用於不需要特殊處理的物件分配,對使用者可見的介面為

linux核心學習 記憶體管理

核心把物理頁作為記憶體管理的基本單位。32位系統 4k 頁 64位系統 8k 頁 由於硬體限制,核心不能對所有頁一視同仁。linux必須處理如下硬體存在的缺陷而引起的記憶體定址問題 linux主要使用了四種區 zone dma 這個區包含的頁只能用來執行dma操作 zone dma32 和zone ...

linux 核心學習 1 記憶體管理

1 分頁機制 早期計算機直接使用實體地址進行記憶體的使用和管理,但是硬體資源有限,而且不同的程式需要使用不同的實體地址,這樣給程式的管理和執行造成了很大的難度,而且極易造成乙個程式覆蓋其他程式的問題,使正常執行的程式出現錯誤。針對以上問題提出了使用虛擬位址與物理位址對映的管理方式,這樣每個程式都可以...

linux核心學習筆記之記憶體管理

linux核心把物理頁作為記憶體管理的基本單位。每一頁的大小根據系統架構不同有所區別,32位系統下為4kb,64位系統下為8kb。記憶體管理單元 mmu 以頁為單位來管理系統中的頁表,負責虛擬位址到實體地址的轉換,使用者所使用的記憶體位址一般都是虛擬位址。核心中頁的結構體中比較重要的成員為 stru...