日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux动态分配全局置换,深入理解计算机系统 第九章 虚拟存储器

發(fā)布時間:2025/3/20 linux 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux动态分配全局置换,深入理解计算机系统 第九章 虚拟存储器 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

虛擬存儲器

定義:

對主存的抽象機制,是硬件異常、硬件地址翻譯、主存、磁盤文件和內(nèi)核軟件的完美交互。

功能:

1. 將主存看成是一個存儲在磁盤上的地址空間的高速緩存,在內(nèi)存中只保存活動區(qū)域,并根據(jù)需要在磁盤和內(nèi)存之間來回傳送數(shù)據(jù)。

2. 為進程提供了一致的地址空間,從而簡化了存儲器管理。

3. 保護了每個進程的地址空間不被其他進程所破壞。

9.1 物理和虛擬地址

CPU通過生成一個虛擬地址(Virtual address,VA)來訪問主存。將虛擬地址轉換為物理地址叫做地址翻譯(address translation)。地址翻譯也需要CPU硬件和操作系統(tǒng)之間的緊密結合。

CPU芯片上有叫做存儲器管理單元(Memory Management Unit,MMU)的專用硬件。利用存儲在主存中的查詢表來動態(tài)翻譯虛擬地址。 查詢表由操作系統(tǒng)管理。

9.2 地址空間

9.3 虛擬存儲器作為緩存的工具

概念上而言,虛擬存儲器(VM)被組織為一個存放在磁盤上的N個連續(xù)字節(jié)大小的單元組成的數(shù)組。每個字節(jié)都有一個唯一的虛擬地址,這個唯一的虛擬地址作為到數(shù)組的索引。磁盤上數(shù)組的內(nèi)容被緩存到主存中。VM系統(tǒng)通過將虛擬存儲器分割為稱為虛擬頁的大小固定的塊來處理磁盤和主存信息交互問題。

任何時候,虛擬頁的集合都被分為3個不相交的子集。

1、[未分配的] VM系統(tǒng)還未分配(或者創(chuàng)建)的頁。未分配的塊沒有任何數(shù)據(jù)與之相關聯(lián)。不占用磁盤空間

2、[緩存的] 當前緩存在物理存儲器的已分配頁。

3、[未緩存的] 沒有緩存在物理頁面存儲器中的已分配頁。

9.3.2 頁表

9.4 虛擬存儲器作為存儲器管理的工具

操作系統(tǒng)為每個進程提供一個獨立的頁表,VM簡化了鏈接和加載,代碼和數(shù)據(jù)共享,以及應用程序的存儲器分配。

1.簡化鏈接

獨立的空間地址意味著每個進程的存儲器映像使用相同的格式。文本節(jié)總是從0x08048000(32位)處

或0x400000(64位)處開始。然后是數(shù)據(jù),bss節(jié),棧。一致性極大簡化了鏈接器的設計和實現(xiàn)。

2.簡化加載

在ELF可執(zhí)行文件中.text和.data節(jié)是連續(xù)的。要把這些節(jié)加載到一個新創(chuàng)建的進程中,linux加載器.

分配虛擬頁的一個連續(xù)的片,從地址0x08048000處(32bit)開始, 或者從0x400000(64bit),

[把這些虛擬頁標記為無效,將頁表條目指向目標文件中適當?shù)奈恢?加載器從不實際拷貝任何數(shù)據(jù)從磁盤到存儲器.]

3.簡化共享

4.簡化存儲器分配

malloc在堆空間分配一個適當數(shù)字(例如k)個連續(xù)的虛擬存儲器頁面,并且將他們映射到物理存儲器中任意

位置的k個任意(不一定連續(xù))的物理頁面。

9.5 虛擬存儲器作為存儲器保護的工具

9.7.2 Linux虛擬存儲器系統(tǒng)

Linux為每個進程維持一個單獨的虛擬地址空間:內(nèi)核虛擬存儲器和進程虛擬存儲器。

內(nèi)核虛擬存儲器包含內(nèi)核中的代碼和數(shù)據(jù)。

1、內(nèi)核虛擬存儲器的某些區(qū)域被映射到所有進程共享的物理頁面.如:內(nèi)核代碼,全局數(shù)據(jù)結構。

2、Linux將一組連續(xù)的虛擬頁面(大小等同于系統(tǒng)DRAM總量)映射到相應的一組物理頁面。[直接映射,不使用頁表]

3、內(nèi)核虛擬存儲器包含每個進程不相同的數(shù)據(jù)。頁表,內(nèi)核在進程上下文中時使用的棧等。

1.Linux 虛擬存儲器區(qū)域

Linux將虛擬存儲器組織成一些區(qū)域(也叫做段)的集合。一個區(qū)域

就是已經(jīng)存在著的(已分配的) 虛擬存儲器的連續(xù)片,這些片/頁已某種形式相關聯(lián)。

如:代碼段,數(shù)據(jù)段,堆,共享庫段,用戶棧。

所有存在的虛擬頁都保存在某個區(qū)域,允許虛擬地址空間有間隙。

虛擬存儲器區(qū)域的內(nèi)核數(shù)據(jù)結構

task_struct

mm_struct: 描述了虛擬存儲器的當前狀態(tài)。

pgd: 指向第一級頁表的基址。當進程運行時,內(nèi)核將pgd存放在CR3控制寄存器

mmap: 指向vm_area_structs的鏈表

vm_area_structs描述了當前虛擬地址空間的一個區(qū)域(area).

vm_start:指向這個區(qū)域的起始處。

vm_end:指向這個區(qū)域的結束處。

vm_port:描述這個區(qū)域內(nèi)包含的所有頁的讀寫許可權限。

vm_flags:描述這個區(qū)域頁面是否與其他進程共享,還是私有等

vm_next: 指向鏈表的下一個區(qū)域。

2.Linux缺頁異常處理

MMU在試圖翻譯虛擬地址A時,觸發(fā)缺頁。這個異常導致控制轉移到缺頁處理程序,執(zhí)行如下步驟:

1、虛擬地址A是合法的嗎? A在某個區(qū)域結構定義的區(qū)域內(nèi)嗎?

解決方法: 缺頁處理程序搜索區(qū)域結構鏈表。把A和每個區(qū)域的vm_start和vm_end做比較。

如果不合法,觸發(fā)段錯誤。

2、試圖訪問的存儲器是否合法? 即:是否有讀,寫,執(zhí)行這個頁面的權限?

如果不合法,觸發(fā)保護異常,終止進程。一切正常的話

3、若不存在以上情況,則選擇犧牲頁,替換,重新執(zhí)行指令

9.8 存儲器映射

定義:

Linux 通過將一個虛擬存儲器區(qū)域與一個磁盤上的對象關聯(lián),以初始化這個虛擬存儲器區(qū)域的內(nèi)容。

虛擬存儲器區(qū)域可以映射到以下兩種類型文件:

1、Unix文件系統(tǒng)中的普通文件:一個區(qū)域可以映射到一個普通磁盤文件的連續(xù)部分。

例如,一個可執(zhí)行文件。文件區(qū)(section)被分成頁大小的片,每一片包含一個虛擬頁面的初始化內(nèi)容。

僅僅是初始化,虛擬頁面此時還并未進入物理存儲器,直到CPU第一次引用這個頁面。

2、匿名文件

匿名文件由內(nèi)核創(chuàng)建,包含的全是二進制零。CPU第一次引用這樣區(qū)域(匿名文件)的虛擬頁面時,

將存儲器中犧牲頁面全部用二進制零覆蓋。并將虛擬頁面標記為駐留在存儲器中。

注意在磁盤和存儲器之間并沒有實際的數(shù)據(jù)傳送。又叫請求二進制零的頁(demand-zero page)。

注意: 一個虛擬頁被初始化了,它就在一個有內(nèi)核維護的專門的交換文件(交換空間)之間切換。

在任何時刻,交換空間都限制著當前運行著的進程能夠分配的虛擬頁面的總數(shù)。

9.8.1 再看共享對象

一個對象可以被映像到虛擬存儲器的一個區(qū)域,要么作為共享對象,要么作為私有對象.

私有對象的寫時拷貝

9.8.2 再看fork函數(shù)

當fork函數(shù)被當前進程調用時:

1、內(nèi)核為新進程創(chuàng)建內(nèi)核數(shù)據(jù)結構,并分配給它唯一一個PID。

2、為了給新進程創(chuàng)建虛擬存儲器[創(chuàng)建頁目錄]。

3、創(chuàng)建了當前進程的mm_struct,區(qū)域結構和頁表的原樣拷貝。

4、將兩個進程的每個頁面都標記為[只讀]。并給兩個區(qū)域進程的每個區(qū)域結構都標記為[私有的寫時拷貝]。

注意:[沒有對物理存儲器進行拷貝,利用的是私有對象的寫時拷貝技術。]

9.8.3 再看execve函數(shù)

假設運行在當前的進程中的程序執(zhí)行了如下的調用:

execve("a.out",NULL,NULL);

execve函數(shù)在當前進程加載并執(zhí)行目標文件a.out中的程序,用a.out代替當前程序。

加載并運行需要以下幾個步驟。

1、刪除已存在的用戶區(qū)域:刪除當前進程虛擬地址的用戶部分中已存在的區(qū)域結構。

2、映射私有區(qū)域:為新程序的文本,數(shù)據(jù),bss和棧區(qū)域創(chuàng)建新的區(qū)域結構。所有新的區(qū)域結構都是私有的,寫時拷貝的。

文本和數(shù)據(jù)區(qū)域被映射到a.out文件中的文件和數(shù)據(jù)區(qū)。bss區(qū)域是請求二進制零,映射到匿名文件。

3、映射共享區(qū)域

4、設置程序計數(shù)器

5、execve最后一件事設置PC指向文本區(qū)域的入口點。

9.8.4 使用mmap函數(shù)的用戶級存儲器映射

Unix進程可以使用mmap函數(shù)來創(chuàng)建新的虛擬存儲器區(qū)域,并將對象映射到這些區(qū)域中

#include

#include

void *mmap(void *start,size_t length,int prot,int flags,int fd,off_t offset);

返回:若成功時則為指向映射區(qū)域的指正,若出錯則為MAP_FAILED(-1).

munmap函數(shù)刪除虛擬存儲器的區(qū)域

#include

#include

void *munmap(void *start,size_t length);

返回:若成功則為0,若出錯則為-1

練習題 9.5代碼

#include

#include

#include

#include

#include "csapp.h" // 自己寫的

#include

#include

int main(int argc, char* argv[]){

if (argc < 2)

csapp_error("lack of filename.");

int fd;

if ((fd = open(argv[1], O_RDWR)) < 0)

csapp_error2("open error",errno);

off_t length;

if ((length = lseek(fd, 0, SEEK_END)) < 0)

csapp_error2("lseek error.",errno);

char* bufptr = (char*)mmap(NULL,length,PROT_READ,MAP_PRIVATE,fd,0);

if (!bufptr)

csapp_error2("mmap error.", errno);

fprintf(stdout,"%s",bufptr);

exit(0);

}

mmap為什么比傳統(tǒng)的讀寫速度要快

mmap : 將文件內(nèi)容直接映射到進程的地址空間,通過對這段內(nèi)存的讀寫,來達到對文件的讀寫目的;

read,write : 每次調用都需要從用戶態(tài)到內(nèi)核態(tài)的切換,且數(shù)據(jù)需要從用戶態(tài)拷貝到內(nèi)核態(tài),然后再寫入磁盤,增加了中間步驟

mmap的缺點 : 不能改變文件長度,無法寫入多余的字符。

9.9 動態(tài)存儲器分配

malloc通過調用sbrk函數(shù)來實現(xiàn)內(nèi)存的分配,且在在sbrk之上加了一層對所分配的內(nèi)存的管理,

而sbrk以及brk是實現(xiàn)從虛擬內(nèi)存到內(nèi)存的映射的

Linux內(nèi)存分配小結--malloc、brk、mmap

動態(tài)存儲器分配器維護著一個進程的虛擬存儲區(qū)域,稱為堆(heap)。

系統(tǒng)之間細節(jié)不同,但是不失通用型。

1、堆是一個請求二進制零的區(qū)域。

2、緊接著未初始化的bss區(qū)域,并向上生長(向更高的地址)。

3、對于每個進程,內(nèi)核維護一個變量[brk],指向堆頂,當堆空間不足時,利用sbrk函數(shù)修改該變量。

4、分配器將堆視為一組不同大小的塊block的集合來維護。

每個塊就是一個連續(xù)的虛擬存儲器片,要么是已分配,要么是空閑。

9.11 C程序中常見的與存儲器有關的錯誤

總結

以上是生活随笔為你收集整理的linux动态分配全局置换,深入理解计算机系统 第九章 虚拟存储器的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。