天天看點

程序虛拟位址空間以及三種記憶體管理方式 分頁式/分段式/段頁式

平時我們都知道位址,是記憶體單元的編号,指針則是存儲變量位址的變量。

那麼程式是否會有位址呢?程式是不占用記憶體的,存儲在磁盤中,隻有當運作時才會将資料載入記憶體中。程序的狹義概念是一個正在運作中的程式(程序詳解看上一篇部落格),是以程序是有位址空間的。

程序虛拟位址空間

假設現在有一個程序,它有一個變量a=100,此時我們建立一個該程序的子程序,子程序的一個特點是代碼共享,資料獨有。

然後在子程序中修改a的值為1,然後運作

int main()
{

        pid_t pid=fork();
        int a=100;
        if(pid==0)
        {
                a=1;
                printf("a=%d \n",a);
                //printf("Pa=%d \n",&a);
        }
        else
        {
                printf("a=%d \n",a);
                //printf("Pa=%d \n",&a);
        }
        return 0;
}

           

運作結果如下,a的值在子程序中确實發生了改變

程式虛拟位址空間以及三種記憶體管理方式 分頁式/分段式/段頁式

那麼,這兩個程序中的a的位址是否相等呢?

程式虛拟位址空間以及三種記憶體管理方式 分頁式/分段式/段頁式

兩個程序中a的位址是相同的,但是同一塊記憶體空間是不能同時存放兩個相同的值的,資料不同,說明這兩個程序中的a的位址肯定不是同一塊記憶體空間,那麼為什麼終端顯示上顯示這兩個a的位址相同呢?

實際上程序通路的位址都是虛拟位址,而我們常說的程序位址空間其實是程序的虛拟位址空間。

如何虛拟一個記憶體空間?

在LINUX系統下,虛拟位址空間實際上是一個 mm_struct的結構體,是對一塊記憶體空間的描述,通過這個描述向程序虛拟出一個連續的,完整的記憶體空間。

如下圖:

程式虛拟位址空間以及三種記憶體管理方式 分頁式/分段式/段頁式

為什麼需要虛拟位址?

為了讓程序不直接通路實體記憶體

如過程序直接通路實體記憶體:

1.程序中的代碼資料使用的是連續的位址空間,如果直接使用連續的實體記憶體會造成記憶體浪費。

2.直接通路實體記憶體會因為缺乏記憶體通路控制而導緻程序的不安全

如何通過虛拟記憶體通路實體記憶體?

作業系統在為程序建立一個虛拟位址空間的時候,同時也建立了一個頁表用于映射虛拟記憶體與實體記憶體的關系。

再回到上面的那個問題,在建立子程序的時候,其實就是複制父程序的PCB,同時父程序的虛拟位址空間也會被複制過去,是以在終端上顯示的位址值才會是相同的,但實際上在實體記憶體中,當子程序中的a發生改變的時候,作業系統已經在記憶體上開辟了一塊新的空間,用于這個改變後的a的資料存儲,然後頁表中關于a在實體記憶體上的映射也會改變到新開辟的記憶體空間上。

這種方式也被成為寫時拷貝技術

寫時拷貝技術:兩個程序一開始指向同一塊空間,等待發生改變的時候,再給子程序重新開辟空間

目的是提高子程序的建立效率。

使用虛拟位址可以實作資料在記憶體上的離散式存儲,提高記憶體使用率。

并且可以在頁表中實作記憶體通路控制。

虛拟位址空間:作業系統向程序通過 mm_struct結構體描述的一個虛假的,連續的,完整的位址空間。

三種記憶體管理方式:

分頁式記憶體管理

分頁式記憶體管理的虛拟位址組成:頁号+頁内偏移

頁号:頁表中頁表項的編号。

頁内偏移:具體一個變量首位址相較于記憶體頁起始位置的偏移量。

頁表主要功能:映射虛拟位址與實體位址的關系/提供記憶體通路控制

通路方式:通過虛拟位址中的頁号和頁内偏移通過頁表找到程序中資料在實體記憶體上的位置。

頁表組成如下:

頁号 實體塊号
2 5
1 6
7

實體記憶體塊号*實體記憶體塊大小+虛拟位址中偏移量=實體記憶體位址

假設記憶體大小為4G,頁大小是4096位元組,則意味着頁号的位是虛拟位址的高二十位,低十二位為頁内便宜。

(4G=2^32, 4096=2^12, 4G/4096=2^20)

分頁式記憶體記憶體管理的優點:将實體記憶體進行分塊管理,通過頁表映射虛拟位址與實體記憶體關系實作資料的離散式存儲,提高記憶體使用率。

分段式記憶體管理

虛拟位址組成:段号+段内偏移

通路方式:通過段表映射程序資料集在實體記憶體中的位置

段表

段号 實體段起始位址

程序首先通過虛拟位址中的資訊找到段号,通過段号在段表中找到在實體記憶體中的起始位置,然後加上段内偏移,就可以得到程序中某個資料集的實體記憶體位址。

優點:使程式員對記憶體的管理更加友善,将記憶體段分為了代碼段,初始化全局段等等段,什麼變量就在什麼段申請空間。

段頁式記憶體管理

顧名思義,就是将分頁式與分段式結合起來的一種記憶體管理方式。

虛拟位址組成:段号+段内頁号+頁内偏移

段表:段号 段内頁表起始位址

頁表:頁号 實體塊号

通路原理:先将程序資料分成若幹段,為每個段進行命名,再将若幹段分成若幹頁

通路方式:程序首先是通過自己的分段找到在段表中相應的段号,然後通過該段表項找到頁表始址,通過頁表項中的實體塊号和頁内偏移通路實體記憶體空間。

程式虛拟位址空間以及三種記憶體管理方式 分頁式/分段式/段頁式

以上三種記憶體管理方式

分頁式:提高了記憶體使用率

分段式:便于管理者/編譯器對記憶體進行管理

段頁式:結合了以上兩種方式的優點

繼續閱讀