目錄
創(chuàng)新互聯(lián)是一家集網(wǎng)站建設(shè),云夢企業(yè)網(wǎng)站建設(shè),云夢品牌網(wǎng)站建設(shè),網(wǎng)站定制,云夢網(wǎng)站建設(shè)報價,網(wǎng)絡(luò)營銷,網(wǎng)絡(luò)優(yōu)化,云夢網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強企業(yè)競爭力??沙浞譂M足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時我們時刻保持專業(yè)、時尚、前沿,時刻以成就客戶成長自我,堅持不斷學(xué)習(xí)、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實用型網(wǎng)站。程序地址空間
進程地址空間 - 虛擬地址空間
概念引入(淺)
初步理解結(jié)構(gòu)
深入理解虛擬地址
為什么要有地址空間?
程序地址空間的角度理解掛起
C/C++在Linux下的程序地址空間分布:
#include#includeint un_g_val;
int g_val = 10;
int main(int argc, char* argv[], char* env[])
{
printf("代碼區(qū):%p\n", main); //代碼區(qū)
char* p = "hello world"; //字面常量
printf("字面常量:%p\n", p);
printf("已初始化全局數(shù)據(jù)區(qū):%p\n", &g_val); //已初始化全局數(shù)據(jù)區(qū)
static int num = 10;
printf("static修飾的局部變量:%p\n", &num); //static
printf("未初始化全局數(shù)據(jù)區(qū):%p\n", &un_g_val); //未初始化全局數(shù)據(jù)區(qū)
char* p1 = (char*)malloc(4);
char* p2 = (char*)malloc(4);
char* p3 = (char*)malloc(4);
printf("堆1:%p\n", p1); //堆
printf("堆2:%p\n", p2); //堆
printf("堆3:%p\n", p3); //堆
printf("棧1:%p\n", &p1); //棧
printf("棧2:%p\n", &p2); //棧
printf("棧3:%p\n", &p3); //棧
for(size_t i = 0; i< argc; ++i)
{
printf("argv[%d]:%p\n", i, argv[i]);
}
for(size_t i = 0; env[i]; ++i)
{
printf("env[%d]:%p\n", i, env[i]);
}
return 0;
}
在我們看來,父子進程是代碼共享的,所以&g_val地址相同是可以理解的,父進程具有獨立性,所以子進程的g_val改變父進程的g_val不變是可以理解點,但是結(jié)合起來看,具有相同地址的變量卻是不同值,就很奇怪。
? 其實,這里地址并不是物理上的地址,而是:虛擬地址(線性地址)。操作系統(tǒng)上的地址與編程語言上的地址是不一樣的,不是一個理解。幾乎所有有?“地址” 的概念的語言,其所謂的地址一定不是物理地址,而是虛擬地址。在操作系統(tǒng)上,接觸不到物理地址,都是虛擬地址,這是操作系統(tǒng)自我的一種保護,防止空間被隨意的更改。
虛擬地址:計算機通過軟硬結(jié)合的方案,創(chuàng)造出的地址空間的概念。
進程地址空間 - 虛擬地址空間 概念引入(淺)初步理解進程地址空間是虛擬地址空間的意義。(計算機的演變)
最初,其實并沒有虛擬地址空間的概念,是CPU直接對物理地址空間(內(nèi)存)操作。
由于物理地址空間就是自由的空間,并未對讀寫設(shè)置權(quán)限,也沒有違規(guī)操作的處理:
初步總結(jié):我們需要一個處理方式,使得CPU運行進程的操作是規(guī)范的,安全的;對于物理地址空間中的進程管理是合理的。
這樣就有了虛擬地址空間的概念。虛擬地址空間的存在就如同一幅圖,一把尺。
一幅圖:
? 直接給進程一個?0x0000……0000 到 0xffff……ffff 的空間,并把每個區(qū)域進行劃分,將代碼與數(shù)據(jù) “畫” 在圖(虛擬地址空間)中。CPU也無需關(guān)注物理內(nèi)存的存在,只需要根據(jù) “圖” 中的位置進行訪問即可,剩下的轉(zhuǎn)換交給操作系統(tǒng),操作系統(tǒng)轉(zhuǎn)換 “圖” 中的虛擬地址變?yōu)槲锢淼刂?,然后將?shù)據(jù)輸出給CPU。也就是說:每一個進程都有一幅針對它的 “圖”,這副 “圖” 是每個進程私有的,而在轉(zhuǎn)換的過程中就是檢測CPU操作是否規(guī)范的關(guān)鍵所在。
? CPU根據(jù)虛擬地址空間的位置向操作系統(tǒng)索要數(shù)據(jù)。
一把尺:
? 對于虛擬的?0x0000……0000 到 0xffff……ffff 區(qū)域的劃分,區(qū)域的劃分就是begin與end:
初步理解結(jié)構(gòu)操作系統(tǒng)將虛擬地址空間中的地址轉(zhuǎn)換為物理地址是通過所謂的頁表。
? CUP通過運行進程,以進程的task_struct結(jié)構(gòu)題提取到虛擬地址空間中所儲存的虛擬地址,該虛擬地址再以頁表的映射關(guān)系找到物理地址,再以此到物理空間中讀取數(shù)據(jù)??梢哉f整個過程CPU都是不知道物理內(nèi)存的存在的,而一直認為虛擬地址空間就是數(shù)據(jù)真正處于的位置。
地址空間和頁表是每一個進程都私有的一份,以每個進程的頁表的映射關(guān)系就能做到:
解決前面的父進程與子進程具有相同的地址,卻g_val值不同的問題:?
fork之后,代碼是父子共享的,所以子進程的地址空間與頁表絕大多數(shù)數(shù)據(jù)都是復(fù)制的父進程的地址空間與頁表數(shù)據(jù),二者是一樣的,前提是并未在子或父進程中更改數(shù)據(jù)。
? 當(dāng)我們更改子進程的g_val的數(shù)據(jù)時:
? 操作系統(tǒng),會以實時拷貝,開辟一個空間將g_val復(fù)制拷貝,改變子進程頁表的映射關(guān)系改變成新開辟的空間,然后進行子進程的g_val的數(shù)據(jù)更改。我們表面上所看的地址只是虛擬地址,其實在物理內(nèi)存中,有屬于自己的變量空間,只不過在用戶層使用同一個變量(虛擬地址)來標(biāo)識。
深入理解虛擬地址? 當(dāng)我們的程序在編譯的時候(形成可執(zhí)行程序的時候),或者說沒被加載到內(nèi)存當(dāng)中的時候,程序內(nèi)部其實就已經(jīng)有地址了。
?地址空間不僅僅是操作系統(tǒng)需要遵守的,其實編譯器也要遵守。即編譯器編譯代碼的時候,就已經(jīng)形成了各個區(qū)域、代碼區(qū)、數(shù)據(jù)區(qū)……,并且采用個Linux內(nèi)核中的一樣的編址方式,給每一個變量,每一行代碼都進行了編址。
? 所以:程序在編譯的時候,每一個字段其實早就已經(jīng)具有了一個虛擬地址。
? 其實這正是地址空間與頁表,最開始的時候的數(shù)據(jù)來源。
為什么要有地址空間?1、凡是非凡的訪問或者是映射,操作系統(tǒng)都會識別到,并終止此進程。
? 因為地址空間和頁表是操作系統(tǒng)創(chuàng)建并維護的。這也就意味著凡是想用地址空間和頁表進行映射,就一定要在操作系統(tǒng)的監(jiān)管之下來進行訪問。也便保護了物理內(nèi)存中所有的合法數(shù)據(jù),包括各個進程以及內(nèi)核的相關(guān)有效數(shù)據(jù)。
更直接的說就是:有效的保護了物理地址。
2、因為有地址空間和頁表的存在,所以在物理內(nèi)存中,可以對未來的數(shù)據(jù)進行任意的位置加載。
? 由于進程與內(nèi)存的聯(lián)系以頁表分隔。對于虛擬地址在內(nèi)存中的物理地址存儲,是由頁表的映射而聯(lián)系的,所以內(nèi)存管理模塊與進程管理模塊就完成了解耦合。
? 所以如C/C++語言上的new、malloc申請空間的時候,本質(zhì)就是在虛擬空間申請。因為對于物理空間申請了,但是無法立馬使用,就會造成空間的浪費,而由于兩個模塊的解耦合,那么兩個模塊的聯(lián)系也就是一個頁表,對于物理空間并沒有立馬給與的必要。只需延遲分配的策略,就可以提高整機的效率。
? 之所以可以延遲分配,本質(zhì)上:因為有地址空間的存在。所以地址 “許諾” 給進程就可以了,上層申請空間就是在地址空間上申請,物理內(nèi)存可以一個bit為都不給。進程既不是立馬運行,那就延遲實現(xiàn)?“許諾” ,提高內(nèi)存的使用。而當(dāng)你真正的對物理地址空間訪問的時候,才執(zhí)行內(nèi)存的相關(guān)管理算法,申請空間,構(gòu)建頁表映射關(guān)系)
?內(nèi)存管理操作系統(tǒng)自動完成。用戶、CPU、進程完全0感知。
3、根據(jù)2,因為在物理內(nèi)存中理論可以任意位置加載,那么物理內(nèi)存中的幾乎所有數(shù)據(jù)和代碼在內(nèi)存中都是亂序的。
? 因為頁表的存在,它可以將地址空間上的虛擬地址與物理地址進行映射,所以可以做到在進程的視角中所有的內(nèi)存分布,是有序的。
?重點:地址空間+頁表 = 內(nèi)存亂序分布變的有序化。
? 不同進程的需要訪問的物理內(nèi)存中的代碼和數(shù)據(jù),是由頁表規(guī)范化,映射到不同的物理內(nèi)存中,進而可以做到進程的獨立性。
?重點:地址空間+頁表 =?內(nèi)存亂序分布變的獨立化。
實現(xiàn)的有序化、獨立化,更是由于地址空間的存在。因為每一個進程都認為自己有一個4GB空間(32位),進而有了虛擬地址分布的地址空間,并通過頁表映射到不同的區(qū)域,實現(xiàn)有序化、獨立化。
程序地址空間的角度理解掛起? 加載的本質(zhì)就是創(chuàng)建進程,按照前面第3點,并不是必須把所有程序的代碼和數(shù)據(jù)加載到內(nèi)存中,并創(chuàng)建內(nèi)核數(shù)據(jù)結(jié)構(gòu)建立映射關(guān)系。在極端的情況下,甚至可能只有內(nèi)核結(jié)構(gòu)被創(chuàng)建出來,并未分配物理空間,這就是未了提高內(nèi)存利用率進行的分批加載,同樣的也有分批換出。
? 當(dāng)已被執(zhí)行完的代碼與數(shù)據(jù),或者由于處于對于某種資源的等待導(dǎo)致的阻塞,也就是此進程短時間不會再執(zhí)行了。進程的數(shù)據(jù)和代碼就換出,也就叫做掛起。
你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機房具備T級流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級服務(wù)器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧
本文名稱:【Linux】--程序地址空間-創(chuàng)新互聯(lián)
轉(zhuǎn)載注明:http://m.rwnh.cn/article0/cejsoo.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供企業(yè)建站、服務(wù)器托管、搜索引擎優(yōu)化、品牌網(wǎng)站建設(shè)、全網(wǎng)營銷推廣、網(wǎng)站改版
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容