最近在看《深刻理解Linux內核》,在第二章《內存尋址》中提到了邏輯地址、線性地址、虛擬地址、物理地址的概念。程序員
原文是這麼描述的:bash
邏輯地址(logical address): 包含在機器語言指令中用來指定一個操做數或一條指令的地址。這種尋址方式在80x86著名的分段結構中表現得尤其具體,它促使MS-DOS或Windows程序員把程序分紅若干段。每個邏輯地址都由一個段(segmemt)和偏移量(offset或displacememt)組成,偏移量指明瞭從段開始的地方到實際地址之間的距離。 線性地址(linear address)(也稱虛擬地址 virtual address): 是一個32爲無符號整數,能夠用來表示高達4GB的地址,也就是,高大4 294 967 296個內存單元。線性地址一般用十六進制數字表示,值的範圍從0x00000000到0xffffffff。 物理地址(physical address): 用於內存芯片級內存單元尋址。它們與從微處理器的地址引腳發送到內存總線上的電信號相對應。物理地址由32位或36位無符號整數表示。
在文中,把線性地址和虛擬地址等同,並詳細定義了邏輯地址。可是,把邏輯地址的定義套入到咱們平時交流中提到的邏輯地址定義,怎麼這麼彆扭呢?code
在工做中,咱們常常把邏輯地址等同於虛擬地址,基本不用線性地址,例如對於如下C程序:內存
#include <stdio.h> #include <stdlie.h> int main(int argc, char **argv) { int var = 1; char *mvar = malloc(10); printf("var address: %p\n", &var); printf("mvar address: %p\n", &mvar); }
執行的結果io
[GMPY@17:04 tmp]$./test var address: 0x7ffe9ddceb9c mvar address: 0x7ffe9ddceba0
咱們在工做中交流時,常常把上面打印出來的地址叫作虛擬地址
,有時候也會叫作邏輯地址
,而非書中這麼複雜這麼繞人的概念。class
那麼,咱們究竟怎麼區分這幾個地址?test
在《深刻理解Linux內核》中描述了 在80x86處理器中 地址的轉換:硬件
邏輯地址 -> [分段單元] ->線性地址 -> [分頁單元] -> 物理地址
其中 分段單元 和 分頁單元 是硬件電路,分別用於 從邏輯地址到虛擬地址 和 從虛擬地址到物理地址的轉換。注意的是,做者特地強調了 在80x86處理器中。分頁
在書中 Linux中的分段 小章節得出一個很是重要的結論:gc
這能夠得出另外一個重要結論,在Linux下邏輯地址與線性地址是一致的,即...
在Linux下邏輯地址與線性地址是一致的!!
既然是一致的,爲何還要區分邏輯地址和線性地址?歷史已經不可究,但不妨礙我 瞎想 遐想:
Intel體系下的工程師提出分段的特色時,爲了區別分段與分頁前的地址,苦思冥想後造出了邏輯地址的概念
爲何要強調是Intel體系呢?由於 以intel爲表明的有限的一些體系規定了要用分段+分頁(arm體系貌似只有分頁)。實際上 與分段相比,Linux更喜歡使用分頁方式,換句話說,Linux不喜歡用分段,可是爲了兼容,只能走走形式,意思意思一下,在實現中讓邏輯地址
≈虛擬地址
若是非要定義邏輯地址,咱們能夠把邏輯地址簡單理解爲
爲了區分分段與分頁的地址,把分段前的地址叫作邏輯地址,把分頁前的地址叫作虛擬地址
在Linux中,咱們能夠認爲 邏輯地址=虛擬地址=線性地址
,所以只剩下兩類地址:
虛擬地址:cpu訪問的地址,即C語言中"%p"打印出來的地址 物理地址:物理內存實際地址,通過MMU從虛擬地址轉換而來
上述僅僅是我的理解,若是有不對的地方,但願一塊兒交流