注:以下** 有的是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...