天天看點

淺談程序虛拟位址空間

本節内容隻讨論32位位址空間

讨論虛拟位址空間前,我們先來觀看一個現象:

父程序未将g_val += 10時:

淺談程式虛拟位址空間

父程序将 g_val += 10;

淺談程式虛拟位址空間

看到結果我們非常困惑,怎麼我父程序和子程序的變量位址一樣,怎麼值不一樣???莫不是作業系統出問題了,給我反回了一個錯誤的答案。其實是由于我們存在程序虛拟位址空間導緻的,我們拿到的位址是虛拟位址,并不是直接存變量的實體位址,實體位址是唯一的,儲存的内容肯定不一樣,是以本質上是由于父程序和子程序中g_val的實體位址映射不同,是以才會得到不同的結果。是以我們使用的 & 取得位址都是虛拟位址。

淺談程式虛拟位址空間

上圖就形象的說明了這個映射過程,當 fork 完成之後,父程序之前的資料,會被父子程序通過頁表結構映射到同一塊實體記憶體上,當有一方修改變量内容時會發生寫時拷貝。

寫時拷貝:

1.當 fork 的時候,如果父子程序不修改資料,則頁表的映射關系不會改變 2.當有一方修改資料時,為了防止導緻另外一方讀取資料時錯誤的,是以需要在實體記憶體當中重新開辟一塊空間,儲存修改後的值,并且将修改的程序的頁表結構當中的映射關系重新指向新的實體記憶體。

頁表結構:

頁表結構有分頁式,分段式和段頁式

分頁式:

1.程序虛拟位址空間分成了一頁一頁的小塊,實體記憶體分成了一塊一塊的小塊,一頁的大小等于一塊的大小 = 4096K 2.頁表維護了頁和塊的關系
淺談程式虛拟位址空間
計算方法: 虛拟位址 = 頁号 + 頁内偏移 頁号 = 虛拟位址 (轉換為10進制) / 塊的大小(4096) 頁内偏移 = 虛拟位址 % 塊的大小 塊的起始位址 = 塊号 * 塊大小(4096) 實體位址 = 塊的起始位址 + 頁内偏移

分段式:

虛拟位址 = 段号 + 段内偏移
淺談程式虛拟位址空間

段頁式:

虛拟位址 = 段号 + 頁号 + 業内偏移
淺談程式虛拟位址空間
通過段号找到頁的起始位址 通過頁的起始位址,找到對應的頁表結構 通過頁号找到對應的塊号,通過塊号,計算出塊的起始位址 塊的起始位址加上頁内偏移計算出實體位址

繼續閱讀