趣談Linux作業系統學習筆記 記憶體管理(22講)

2022-09-07 17:54:15 字數 4169 閱讀 6387

記憶體管理資訊: task_struct 的 mm_struct 中

整個虛擬記憶體空間:

1)是使用者態位址空間

2)是核心態位址空間

那這兩部分的分界線在**呢?這就要 task_size 來定義

1

#ifdef config_x86_322/*

3* user space process size: 3gb (default).4*/

5#define task_size page_offset

6#define task_size_max task_size7/*

8config page_offset

9hex

10default 0xc0000000

11depends on x86_32

12*/

13#else

14/*

15* user space process size. 47bits minus one guard page.

16*/

17#define task_size_max ((1ul << 47) - page_size)

18#define task_size (test_thread_flag(tif_addr32) ? \

19ia32_page_offset : task_size_max)

20 ......

對於 32 位系統: 最大能夠定址 2^32=4g,其中使用者態虛擬位址空間是 3g,核心態是 1g

對於 64 位系統:

虛擬位址只使用了 48 位。就像 **裡面:寫的一樣,1 左移了 47 位,就相當於 48 位位址空間一半的位置,0x0000800000000000,然後減去乙個頁,就是 0x00007ffffffff000,共 128t。同樣,核心空間也是 128t。核心空間和使用者空間之間隔著很大的空隙,以此來進行隔離

使用者態布局

使用者態虛擬空間的布局

1 unsigned long mmap_base;  /*

base of mmap area

*/2 unsigned long total_vm; /*

*/3 unsigned long locked_vm; /*

pages that h**e pg_mlocked set

*/4 unsigned long pinned_vm; /*

refcount permanently increased

*/5 unsigned long data_vm; /*

vm_write & ~vm_shared & ~vm_stack

*/6 unsigned long exec_vm; /*

vm_exec & ~vm_write & ~vm_stack

*/7 unsigned long stack_vm; /*

vm_stack

*/8 unsigned long

start_code, end_code, start_data, end_data;

9 unsigned long

start_brk, brk, start_stack;

10 unsigned long arg_start, arg_end, env_start, env_end;

1 ) mmap_base: 表示虛擬位址空間中用於記憶體對映的起始位址。一般情況下,這個空間是從高位址到低位址增長的。前面咱們講 malloc 申請一大塊記憶體的時候,就是通過 mmap 在這裡對映一塊區域到物理記憶體。咱們載入動態鏈結庫 so 檔案,也是在這個區域裡面,對映一塊區域到 so 檔案

2 ) total_vm: 是總共對映的頁的數目。我們知道,這麼大的虛擬位址空間,不可能都有真實記憶體對應,所以這裡是對映的數目。當記憶體吃緊的時候,有些頁可以換出到硬碟上,有的頁因為比較重要,不能換出。

3 ) locked_vm: 是被鎖定不能換出

4 ) pinned_vm 是不能換出,也不能移動

5 ) data_vm: 是存放資料的頁的數目,exec_vm 是存放可執行檔案的頁的數目,stack_vm 是棧所佔的頁的數目

6 ) start_code 和 end_code 表示可執行**的開始和結束位置,start_data 和 end_data 表示已初始化資料的開始位置和結束位置

7 ) start_brk 是堆的起始位置,brk 是堆當前的結束位置。前面咱們講過 malloc 申請一小塊記憶體的話,就是通過改變 brk 位置實現的

8 ) start_stack 是棧的起始位置,棧的結束位置在暫存器的棧頂指標中

9 ) arg_start 和 arg_end 是引數列表的位置, env_start 和 env_end 是環境變數的位置。它們都位於棧中最高位址的地方

示圖:

load_elf_binary 實現vm_area_struct 和上面的記憶體區域關聯

1)load_elf_binary 會完成以下的事情:

2)呼叫 setup_new_exec,設定記憶體對映區 mmap_base;

3)呼叫 setup_arg_pages,設定棧的 vm_area_struct,這裡面設定了 mm->arg_start 是指向棧底的,current->mm->start_stack 就是棧底;

4)elf_map 會將 elf 檔案中的**部分對映到記憶體中來;

5)set_brk 設定了堆的 vm_area_struct,這裡面設定了 current->mm->start_brk = current->mm->brk,也即堆裡面還是空的;

6)load_elf_interp 將依賴的 so 對映到記憶體中的記憶體對映區域

對映完畢後,什麼情況下會修改呢?

第一種情況是函式的呼叫,涉及函式棧的改變,主要是改變棧頂指標。

第二種情況是通過 malloc 申請乙個堆內的空間,當然底層要麼執行 brk,要麼執行 mmap

核心態的布局

32 位的核心態虛擬位址空間一共就 1g,佔絕大部分的前 896m,我們稱為直接對映區

64 位的核心主要包含以下幾個部分:

從 0xffff800000000000 開始就是核心的部分,只不過一開始有 8t 的空檔區域。

從 __page_offset_base(0xffff880000000000) 開始的 64t 的虛擬位址空間是直接對映區域,也就是減去 page_offset 就是實體地址。虛擬位址和實體地址之間的對映在大部分情況下還是會通過建立頁表的方式進行對映。

從 vmalloc_start(0xffffc90000000000)開始到 vmalloc_end(0xffffe90000000000)的 32t 的空間是給 vmalloc 的。

從 vmemmap_start(0xffffea0000000000)開始的 1t 空間用於存放物理頁面的描述結構 struct page 的。

從 __start_kernel_map(0xffffffff80000000)開始的 512m 用於存放核心**段、全域性變數、bss 等。這裡對應到物理記憶體開始的位置,減去 __start_kernel_map 就能得到物理記憶體的位址。這裡和直接對映區有點像,但是不矛盾,因為直接對映區之前有 8t 的空當區域,早就過了核心**在物理記憶體中載入的位置

作業系統學習筆記

這裡專門摘錄作業系統相關筆試題和面試題!也當作自己的乙個複習!乙個很全的作業系統常考知識集合 1.分段式儲存和分頁式儲存,以及段頁式儲存的區別 分頁是一維儲存,分段是二維的 因為分頁給出虛擬位址後,作業系統會自動劃分頁號和偏移量 而分段給出位址後,需要知道段號和偏移量,段的長度是可變的!故是二維的 ...

作業系統學習 筆記

單道批處理評價 資源利用率差 互動性差 等 多道批處理 w為了提高系統的利用率 出現多道批處理 多道 是指 某時刻 多個應用程式再主存中,按照某些原則去處理,逐個執行程式。批處理 使用者提交一批作業,首先存放再外存,排成乙個佇列,然後排程程式按一定的演算法去排程從該佇列 中選取佇列中的乙個或若干個作...

作業系統學習筆記

為什麼需要多執行緒?乙個程序有不同的任務,譬如說乙個程式有不同的方法,有些任務需要等待其他資源的排程 io排程 此時的cpu會空閒等待,加入多執行緒之後,程序分為不同的執行緒去執行不同的任務,使得cpu的利用率大大提高。多執行緒和多程序的區別 多程序是執行不同的程式,多程序切換需要中斷 記錄斷點等資...