1. 程式人生 > 其它 >89-我們看到的地址是虛擬地址還是實體地址?

89-我們看到的地址是虛擬地址還是實體地址?

技術標籤:C語言

請看下列程式碼

#include <stdio.h>
#include <stdlib.h>
int a = 1, b = 255;
int main()
{
	int *p= &a;
	printf("p = %X, &b = %X\n", p, &b);
	return 0;

}

在這裡插入圖片描述

在C語言中,指標變數的值就是一個記憶體地址,&運算子的作用也是取變數的記憶體地址
程式碼中的 a、b 是全域性變數,它們的記憶體地址在連結時就已經決定了,以後再也不能改變,該程式無論在何時執行,結果都是一樣的。那麼問題來了,如果實體記憶體中的這兩個地址被其他程式佔用了怎麼辦,我們的程式豈不是無法運行了?

幸運的是,這些記憶體地址都是假的,不是真實的實體記憶體地址,而是虛擬地址。虛擬地址通過CPU的轉換才能對應到實體地址,而且每次程式執行時,作業系統都會重新安排虛擬地址和實體地址的對應關係,哪一段實體記憶體空閒就使用哪一段。
虛擬地址–>記憶體對映機制–>實體地址
虛擬地址的整個想法是這樣的:把程式給出的地址看做是一種虛擬地址(Virtual Address),然後通過某些對映的方法,將這個虛擬地址轉換成實際的實體地址。這樣,只要我們能夠妥善地控制這個虛擬地址到實體地址的對映過程,就可以保證程式每次執行時都可以使用相同的地址。
除了在程式設計時可以使用固定的記憶體地址,給程式設計師帶來方便外,使用虛擬地址還能夠使不同程式的地址空間相互隔離,提高記憶體使用效率。

如果所有程式都直接使用實體記憶體,那麼程式所使用的地址空間不是相互隔離的。惡意程式可以很容易改寫其他程式的記憶體資料,以達到破壞的目的;有些非惡意、但是有 Bug 的程式也可能會不小心修改其他程式的資料,導致其他程式崩潰。
這對於需要安全穩定的計算機環境的使用者來說是不能容忍的,使用者希望他在使用計算機的時候,其中一個任務失敗了,至少不會影響其他任務。
使用了虛擬地址後,程式A和程式B雖然都可以訪問同一個地址,但它們對應的實體地址是不同的,無論如何操作,都不會修改對方的記憶體。

使用虛擬地址後,作業系統會更多地介入到記憶體管理工作中,這使得控制記憶體許可權成為可能。例如,我們希望儲存資料的記憶體沒有執行許可權,儲存程式碼的記憶體沒有修改許可權,作業系統佔用的記憶體普通程式沒有讀取許可權等。

另外,當實體記憶體不足時,作業系統能夠更加靈活地控制換入換出的粒度,磁碟 I/O 是非常耗時的工作,這能夠從很大程度上提高程式效能。

在計算機中,為了讓操作更加直觀、易於理解、增強使用者體驗,開發者經常會使用一件法寶——增加中間層,即使用一種間接的方式來遮蔽複雜的底層細節,只給使用者提供簡單的介面。虛擬地址是使用中間層的一個典型例子。