定義html
對主存的抽象機制,是硬件異常、硬件地址翻譯、主存、磁盤文件和內核軟件的完美交互。linux
功能數組
- 將主存當作是一個存儲在磁盤上的地址空間的高速緩存,在內存中只保存活動區域,並根據須要在磁盤和內存之間來回傳送數據。
CPU經過生成一個虛擬地址(Virtual address,VA)來訪問主存。將虛擬地址轉換爲物理地址叫作地址翻譯(address translation)。地址翻譯也須要CPU硬件和操做系統之間的緊密結合。緩存
CPU芯片上有叫作存儲器管理單元(Memory Management Unit,MMU)的專用硬件。利用存儲在主存中的查詢表來動態翻譯虛擬地址。 查詢表由操做系統管理。安全
概念上而言,虛擬存儲器(VM)被組織爲一個存放在磁盤上的N個連續字節大小的單元組成的數組。每一個字節都有一個惟一的虛擬地址,這個惟一的虛擬地址做爲到數組的索引。磁盤上數組的內容被緩存到主存中。VM系統經過將虛擬存儲器分割爲稱爲虛擬頁的大小固定的塊來處理磁盤和主存信息交互問題。
任什麼時候候,虛擬頁的集合都被分爲3個不相交的子集。數據結構
一、[未分配的] VM系統還未分配(或者建立)的頁。未分配的塊沒有任何數據與之相關聯。不佔用磁盤空間
二、[緩存的] 當前緩存在物理存儲器的已分配頁。
三、[未緩存的] 沒有緩存在物理頁面存儲器中的已分配頁。
函數
操做系統爲每一個進程提供一個獨立的頁表,VM簡化了連接和加載,代碼和數據共享,以及應用程序的存儲器分配。
工具
1.簡化連接學習
獨立的空間地址意味着每一個進程的存儲器映像使用相同的格式。文本節老是從0x08048000(32位)處
或0x400000(64位)處開始。而後是數據,bss節,棧。一致性極大簡化了連接器的設計和實現。操作系統
2.簡化加載
在ELF可執行文件中.text和.data節是連續的。要把這些節加載到一個新建立的進程中,linux加載器.
分配虛擬頁的一個連續的片,從地址0x08048000處(32bit)開始, 或者從0x400000(64bit),
[把這些虛擬頁標記爲無效,將頁表條目指向目標文件中適當的位置,加載器從不實際拷貝任何數據從磁盤到存儲器.]
3.簡化共享
4.簡化存儲器分配
malloc在堆空間分配一個適當數字(例如k)個連續的虛擬存儲器頁面,而且將他們映射到物理存儲器中任意
位置的k個任意(不必定連續)的物理頁面。
Linux虛擬存儲器系統
內核虛擬存儲器包含內核中的代碼和數據。
一、內核虛擬存儲器的某些區域被映射到全部進程共享的物理頁面.如:內核代碼,全局數據結構。
二、Linux將一組連續的虛擬頁面(大小等同於系統DRAM總量)映射到相應的一組物理頁面。[直接映射,不使用頁表]
三、內核虛擬存儲器包含每一個進程不相同的數據。頁表,內核在進程上下文中時使用的棧等。
虛擬存儲器區域的內核數據結構
task_struct mm_struct: 描述了虛擬存儲器的當前狀態。 pgd: 指向第一級頁表的基址。當進程運行時,內核將pgd存放在CR3控制寄存器 mmap: 指向vm_area_structs的鏈表 vm_area_structs描述了當前虛擬地址空間的一個區域(area). vm_start:指向這個區域的起始處。 vm_end:指向這個區域的結束處。 vm_port:描述這個區域內包含的全部頁的讀寫許可權限。 vm_flags:描述這個區域頁面是否與其餘進程共享,仍是私有等 vm_next: 指向鏈表的下一個區域。
定義
Linux 經過將一個虛擬存儲器區域與一個磁盤上的對象關聯,以初始化這個虛擬存儲器區域的內容。
虛擬存儲器區域能夠映射到如下兩種類型文件:
一、Unix文件系統中的普通文件:一個區域能夠映射到一個普通磁盤文件的連續部分。
例如,一個可執行文件。文件區(section)被分紅頁大小的片,每一片包含一個虛擬頁面的初始化內容。
僅僅是初始化,虛擬頁面此時還並未進入物理存儲器,直到CPU第一次引用這個頁面。二、匿名文件
匿名文件由內核建立,包含的全是二進制零。CPU第一次引用這樣區域(匿名文件)的虛擬頁面時,
將存儲器中犧牲頁面所有用二進制零覆蓋。並將虛擬頁面標記爲駐留在存儲器中。
注意在磁盤和存儲器之間並無實際的數據傳送。又叫請求二進制零的頁(demand-zero page)。
注意: 一個虛擬頁被初始化了,它就在一個有內核維護的專門的交換文件(交換空間)之間切換。
在任什麼時候刻,交換空間都限制着當前運行着的進程可以分配的虛擬頁面的總數。
一個對象能夠被映像到虛擬存儲器的一個區域,要麼做爲共享對象,要麼做爲私有對象.
私有對象的寫時拷貝
當fork函數被當前進程調用時:
一、內核爲新進程建立內核數據結構,並分配給它惟一一個PID。
二、爲了給新進程建立虛擬存儲器[建立頁目錄]。
三、建立了當前進程的mm_struct,區域結構和頁表的原樣拷貝。
四、將兩個進程的每一個頁面都標記爲[只讀]。並給兩個區域進程的每一個區域結構都標記爲[私有的寫時拷貝]。
注意:[沒有對物理存儲器進行拷貝,利用的是私有對象的寫時拷貝技術。]
Unix進程可使用mmap函數來建立新的虛擬存儲器區域,並將對象映射到這些區域中
#include <unistd.h> #include <sys/mman.h> void *mmap(void *start,size_t length,int prot,int flags,int fd,off_t offset); 返回:若成功時則爲指向映射區域的指正,若出錯則爲MAP_FAILED(-1).
munmap函數刪除虛擬存儲器的區域
#include <unistd.h>
#include <sys/mman.h>
void *munmap(void *start,size_t length); 返回:若成功則爲0,若出錯則爲-1
1.mmap爲何比傳統的讀寫速度要快
mmap : 將文件內容直接映射到進程的地址空間,經過對這段內存的讀寫,來達到對文件的讀寫目的;
read,write : 每次調用都須要從用戶態到內核態的切換,且數據須要從用戶態拷貝到內核態,而後再寫入磁盤,增長了中間步驟
mmap的缺點 : 不能改變文件長度,沒法寫入多餘的字符。
2.如何調用execve函數
假設運行在當前的進程中的程序執行了以下的調用:
execve("a.out",NULL,NULL);
加載並運行須要如下幾個步驟
一、刪除已存在的用戶區域:刪除當前進程虛擬地址的用戶部分中已存在的區域結構。
二、映射私有區域:爲新程序的文本,數據,bss和棧區域建立新的區域結構。全部新的區域結構都是私有的,寫時拷貝的。
文本和數據區域被映射到a.out文件中的文件和數據區。bss區域是請求二進制零,映射到匿名文件。三、映射共享區域
四、設置程序計數器
五、execve最後一件事設置PC指向文本區域的入口點。
代碼託管
- [5324](博客連接) - 結對照片 - 結對學習內容 第九章
代碼行數(新增/累積) | 博客量(新增/累積) | 學習時間(新增/累積) | 重要成長 | |
---|---|---|---|---|
目標 | 5000行 | 30篇 | 400小時 | |
第十一週 | 300/2000 | 2/2 | 200/400 |
嘗試一下記錄「計劃學習時間」和「實際學習時間」,到期末看看能不能改進本身的計劃能力。這個工做學習中很重要,也頗有用。
耗時估計的公式
:Y=X+X/N ,Y=X-X/N,訓練次數多了,X、Y就接近了。
計劃學習時間:XX小時
實際學習時間:XX小時
改進狀況:
(有空多看看現代軟件工程 課件
軟件工程師能力自我評價表)