天天看點

c++ 讀取記憶體資料 基址_什麼是實體位址?不知道沒關系,今天程式員帶你認識各種記憶體位址...什麼是線性位址和虛拟位址?什麼是邏輯位址和有效位址?總結最後

實體位址

就是記憶體單元的絕對位址,實體位址0x0000就表示記憶體條的第一個存儲單元,0x0010(16進制)就表示記憶體條的第17個存儲單元,一個存儲單元是1byte(8bit)。

你問為什麼是1byte?

c++ 讀取記憶體資料 基址_什麼是實體位址?不知道沒關系,今天程式員帶你認識各種記憶體位址...什麼是線性位址和虛拟位址?什麼是邏輯位址和有效位址?總結最後

一個記憶體條是由若幹個黑色的記憶體顆粒構成的。每一個記憶體顆粒叫做一個chip。

c++ 讀取記憶體資料 基址_什麼是實體位址?不知道沒關系,今天程式員帶你認識各種記憶體位址...什麼是線性位址和虛拟位址?什麼是邏輯位址和有效位址?總結最後

每個chip中又疊了若幹bank

c++ 讀取記憶體資料 基址_什麼是實體位址?不知道沒關系,今天程式員帶你認識各種記憶體位址...什麼是線性位址和虛拟位址?什麼是邏輯位址和有效位址?總結最後

在每個bank内部,就是電容的行列矩陣結構了,每一個元素有8個小電容,存儲8個bit,也就是一個位元組。

什麼是線性位址和虛拟位址?

在80286系列以前,CPU隻支援實模式操作模式。16位寄存器想要對20位位址線進行尋址,使用分段機制,段基址(16位) x 16(左移4位) + 段内偏移位址(4位)就是實體位址了。這樣的好處是所見即所得,程式員指定的位址就是實體位址,實體位址對程式員是可見的。同時也帶來了一些問題:1) 無法支援多任務。2) 程式的安全性無法得到保證。(根本原因就是一個程式直接修改了其他程式的記憶體,導緻崩潰)

c++ 讀取記憶體資料 基址_什麼是實體位址?不知道沒關系,今天程式員帶你認識各種記憶體位址...什麼是線性位址和虛拟位址?什麼是邏輯位址和有效位址?總結最後

80286系列則是被設計來解決這些問題,段式訪存得到的改進,原來段基址+段内偏移得到的位址不再是實際的實體位址,而是被稱作為線性位址,要經過一個轉換層轉換才變成一個實體位址。這種CPU操作模式就被稱為保護模式了。保護的是:厘清楚各個程式使用的存儲區域,不允許随便跨界通路。

c++ 讀取記憶體資料 基址_什麼是實體位址?不知道沒關系,今天程式員帶你認識各種記憶體位址...什麼是線性位址和虛拟位址?什麼是邏輯位址和有效位址?總結最後

80286系列之後就進入32位CPU時代了,32位寄存器可以直接通路32位位址總線。但是在保護模式下,位址仍然采用“段位址:偏移位址”的方式來表示。段值仍然由原來的16位的cs、ds等寄存器表示,但是此時它們僅僅是一個索引,這些個索引指向一個資料結構的表項,表項中詳細定義了一個段的起始位址、界限、屬性等内容,這個資料結構,叫做GDT(其實還可能是LDT),GDT中的每一個表項,叫做描述符。這裡我們就詳細看一下保護模式的尋址方式吧。

c++ 讀取記憶體資料 基址_什麼是實體位址?不知道沒關系,今天程式員帶你認識各種記憶體位址...什麼是線性位址和虛拟位址?什麼是邏輯位址和有效位址?總結最後

1) 尋址時,先找到gdtr寄存器,從中得到GDT的基址。2) 有了GDT的基址,又有段寄存器中儲存的索引,可以得到段寄存器“所指”的那個表項,即所指的那個描述符。3) 得到了描述符,就可以從描述符中得到該描述符所描述的那個段的起始位址。4) 有了段的起始位址,将偏移位址拿過來與之相加,便能得到最後的線性位址。5) 有了線性位址,經過變換,即可得到相應的實體位址。

c++ 讀取記憶體資料 基址_什麼是實體位址?不知道沒關系,今天程式員帶你認識各種記憶體位址...什麼是線性位址和虛拟位址?什麼是邏輯位址和有效位址?總結最後

保護模式雖然解決了記憶體不被跨界通路,但是其也帶來了新的問題,那就是記憶體碎片。首先我們了解一下記憶體碎片為何産生:首先假設我們有10B記憶體:

ID首位址尾位址長度狀态00910空閑

c++ 讀取記憶體資料 基址_什麼是實體位址?不知道沒關系,今天程式員帶你認識各種記憶體位址...什麼是線性位址和虛拟位址?什麼是邏輯位址和有效位址?總結最後

當程式申請一個長度為3的記憶體空間後:

c++ 讀取記憶體資料 基址_什麼是實體位址?不知道沒關系,今天程式員帶你認識各種記憶體位址...什麼是線性位址和虛拟位址?什麼是邏輯位址和有效位址?總結最後

ID首位址尾位址長度狀态00231397空閑

當程式再申請一個長度為2,以及長度為4的記憶體空間後:

c++ 讀取記憶體資料 基址_什麼是實體位址?不知道沒關系,今天程式員帶你認識各種記憶體位址...什麼是線性位址和虛拟位址?什麼是邏輯位址和有效位址?總結最後

ID首位址尾位址長度狀态0023134225843991空閑

此時,隻剩1個可用空間。如果這時程式再來申請長度大于1的空間,就申請不了,也就是記憶體不夠。現在,釋放掉ID=1的空間:

c++ 讀取記憶體資料 基址_什麼是實體位址?不知道沒關系,今天程式員帶你認識各種記憶體位址...什麼是線性位址和虛拟位址?什麼是邏輯位址和有效位址?總結最後

ID首位址尾位址長度狀态00231342空閑25843991空閑

我們發現,現在可用記憶體空間為3,但是,這3個空閑空間,并不是連續的。是以,如果程式現在申請長度為3的記憶體空間,同樣會申請不了,會出現記憶體不夠。我們把這種情況,稱之為記憶體碎片。

那記憶體碎片怎麼解決呢?于是就有了分頁機制,接下來我們詳細講一下分頁:首先,把實體記憶體,按照某種尺寸,進行平均分割。比如我現在以2個記憶體機關,來分割記憶體,也就是每兩個連續的記憶體空間,組成一個記憶體頁:

c++ 讀取記憶體資料 基址_什麼是實體位址?不知道沒關系,今天程式員帶你認識各種記憶體位址...什麼是線性位址和虛拟位址?什麼是邏輯位址和有效位址?總結最後

位址頁ID狀态00空閑121空閑342空閑563空閑784空閑9

接着,系統同樣需要維護一個記憶體資訊表:

c++ 讀取記憶體資料 基址_什麼是實體位址?不知道沒關系,今天程式員帶你認識各種記憶體位址...什麼是線性位址和虛拟位址?什麼是邏輯位址和有效位址?總結最後

ID使用的記憶體頁ID

現在,程式申請長度為3的記憶體空間,不過由于現在申請的最小機關為頁面,而一個頁面的長度為2,是以現在需要申請2個頁面,也就是4個記憶體空間。你看,這就浪費了1個記憶體空間。

c++ 讀取記憶體資料 基址_什麼是實體位址?不知道沒關系,今天程式員帶你認識各種記憶體位址...什麼是線性位址和虛拟位址?什麼是邏輯位址和有效位址?總結最後

位址頁ID狀态00121342空閑563空閑784空閑9

ID使用的記憶體頁ID00,1

接着,程式再申請長度為1,長度為2的空間:

c++ 讀取記憶體資料 基址_什麼是實體位址?不知道沒關系,今天程式員帶你認識各種記憶體位址...什麼是線性位址和虛拟位址?什麼是邏輯位址和有效位址?總結最後

位址頁ID狀态00121342563784空閑9

ID使用的記憶體頁ID00,11223

釋放掉ID=1,記憶體頁ID為2的那條記憶體空間資訊:

c++ 讀取記憶體資料 基址_什麼是實體位址?不知道沒關系,今天程式員帶你認識各種記憶體位址...什麼是線性位址和虛拟位址?什麼是邏輯位址和有效位址?總結最後

位址頁ID狀态00121342空閑563784空閑9

ID使用的記憶體頁ID00,123

現在,就出現了之前的情況:目前一共有4個記憶體空間,但是不連續。不過,因為現在是分頁管理機制,是以,現在仍然可以繼續申請長度為4的記憶體空間。沒有碎片,能夠盡量地全部用完空間。但仔細想想,這種優勢背後,也是需要付出大量代價的。分頁的方式下,程式需要記錄記憶體頁ID,每次使用時,需要從記憶體頁ID翻譯成實際記憶體位址,多了一次轉換。而且這種模式,會浪費一些記憶體,比如上面申請3個記憶體空間,實際配置設定了2個頁面共4個記憶體空間,浪費了1個記憶體空間。

c++ 讀取記憶體資料 基址_什麼是實體位址?不知道沒關系,今天程式員帶你認識各種記憶體位址...什麼是線性位址和虛拟位址?什麼是邏輯位址和有效位址?總結最後

還有一個要注意的地方,這個時候"段基址+段内偏移位址"經過段部件處理後得到的線性位址就不再是實體位址了,而是虛拟位址了。從下圖我們能夠清楚的看出來我們最後的線性位址表示的是頁表的位址,而不是實體位址了。

c++ 讀取記憶體資料 基址_什麼是實體位址?不知道沒關系,今天程式員帶你認識各種記憶體位址...什麼是線性位址和虛拟位址?什麼是邏輯位址和有效位址?總結最後

什麼是邏輯位址和有效位址?

無論CPU在什麼模式下,段内偏移位址又稱為有效位址或者邏輯位址(隻是叫法不一樣罷了),例如實模式下mov ax, [0x7c00],0x7c00就是邏輯位址(或有效位址),但這條指令最終操作的實體位址是DS*16+0x7c00。Linux最初就是在32位的80386系列上設計的,并且沒有使用分段機制,是以在Linux上邏輯位址和線性位址就是一回事了。

總結

一圖以概括:

c++ 讀取記憶體資料 基址_什麼是實體位址?不知道沒關系,今天程式員帶你認識各種記憶體位址...什麼是線性位址和虛拟位址?什麼是邏輯位址和有效位址?總結最後

最後

如果你處于想學Python或者正在學習Python,Python的教程不少了吧,但是是最新的嗎?說不定你學了可能是兩年前人家就學過的内容,在這小編分享一波2020最新的Python教程。擷取方式,私信小編 “ 01 ”,即可免費擷取哦!

繼續閱讀