日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

 進程、線程有什么區別?虛擬地址和物理地址有什么區別?讓我們用一只青蛙的視角,來解讀它們背后的秘密

進程、線程、虛擬地址、物理地址,這些名詞既熟悉也陌生!似乎無論看多少資料,都很難準確地弄清楚它們之間的差異和存在的意義。今天我們用CPU的視角,再次會會這個老朋友,看看你是否有新的啟發?

 

奇怪的內存

先寫一個最簡單的程序。這個程序只做兩件事情:定義一個全局變量 a,并賦值為:1;然后打印出 a 的地址和數值

#include <stdio.h>
#include <unistd.h>


int a = 1;
int main()
{
    printf("address: %p, value: %dn", &a, a);
    sleep(10000000);
}

將上面的代碼,編輯成可執行程序:p1;接著,修改一下代碼:給全局變量 a 賦值為:2,再次編譯出可執行程序:p2。

好了,兩個程序:p1,p2 都準備好了,讓我們再以兩個進程的形式,運行它們:左邊的窗口進程,運行p1;右邊的窗口進程,運行p2

 

發現問題了嗎?無論是 p1 還是 p2,它們輸出的 a 的地址都是一樣的,但 a 的值卻不一樣!難道同一個內存地址里面,既能存放 1,也能存放 2?

當然不是,原來0x555555558010是虛擬地址,并不是真實的物理內存地址,進程p1的0x555555558010,跟進程p2的0x555555558010,沒有任何關系!

虛擬地址,只在進程內,是有意義的;可以用來指示不同變量,所對應的不同內存地址;但一旦跳出單一進程,在進程之間比較虛擬地址,就沒有任何意義了!

 

MMU

是什么軟件,擁有如此的魔力?能讓進程p1和進程p2的內存空間完全隔離?答案不是軟件,而是硬件 — 現代CPU的協處理器:MMU

MMU的工作原理,未來我們還會詳細闡述,這里只說結論:無論是進程p1,還是進程p2的,它們的變量 a 的地址都是虛擬地址,看上去是同一個地址,但實際上,已經被 MMU 映射到了不同的物理地址上去了。這就是“進程”最顯著的特點:空間獨立性。

 

舉個例子,進程就像一只井底之蛙,它固執地認為:自己已經擁有整個天空;但它永遠不知道:天空到底有多大。更不知道:周圍還有很多跟它有一樣想法的井底之蛙,而 MMU 就是束縛這些青蛙視野的井,每一口井,就是一個:進程空間。

 


 

進程 vs 線程

那看來全是 MMU 惹的禍,不要 MMU 行嗎?當然可以,但一旦沒有井的束縛,所有的青蛙,都跳到地面上,它們都可以看到一個完整的天空,所以,沒有 MMU,進程也就不存在了,進程被降級成了:線程。

這樣的例子很多,例如:在沒有 MMU 的單片機。你就只會遇到線程或者叫:task,根本沒有“進程”的概念。

在 MMU 出現之前,計算機的世界里面,只有“線程”,在 MMU 出現之后,“進程”才真正落地,因為沒有 MMU,就沒有辦法實現:內存空間的隔離,也就根本無法實現“進程”要求的:空間獨立性。

至于“進程”中的多“線程”就很容易理解了。就是:一堆青蛙,都放在一個井里。而且,它們都認為自己擁有整個天空。

 

因為,這些“線程”都處于同一個“進程”空間中,大家可以相互訪問,完全沒有任何限制。這使得用“線程”實現多任務編程,會非常便利。

 

但也因為這種對安全的忽視,一旦任何一個“線程”崩潰

 

所有的“線程”都不能幸免,大家一榮俱榮,一損俱損!

 

所以,網絡服務器一般都會使用“多進程”,而很少使用“多線程”。這樣即使某一個用戶的服務進程崩潰了,其他“進程”還能繼續正常工作。這樣,就不會因為某個用戶的訪問失敗,而導致其他用戶也無法訪問服務器。

 

好了,這可能就是你永遠弄不清楚:“線程”和“進程”的原因,因為,這不僅僅是:一個軟件問題,更是一個 MMU 的問題。以后你再跟人討論“線程”、“進程”的時候,一定要先問一下:有 MMU 嗎?

 

總結

  1. 進程就像一只井底之蛙,雖然看上去,它可以讀/寫整個64位(假設CPU是64位的)的虛擬內存空間:void write_memory()
    {char*p = 0;
    for(unsigned long offset = 0; offset<= 0xFFFFFFFFFFFFFFFF; offset++)
    {*(p + offset) = 0x55;
    }} 但天到底有多大,真實的物理內存空間到底有多少?除了操作系統和MMU,沒有人能知道。
  2. 進程間的空間隔離,讓進程之間的信息共享沒有線程那么方便,但也大大提高了整個系統的安全性;再也不會因為某一個應用程序的崩潰,導致計算機重啟。還記得紅白機上的reset按鍵嗎?

 

任何一個游戲程序的崩潰,都需要通過reset來重啟/恢復系統。

3. 進程間的空間隔離,讓惡意程序無法再掃描整其他程序的內存或整個物理內存,任何程序只能在自己的一畝三分地里面干活。通過游戲修改器,玩《仙劍奇俠傳》的日子,不會再有了。

 

這樣看來:生活在“井”里,也沒有什么不好。

 

熱點問題

Q1:誰在分配:虛擬地址?

A1:程序員在代碼中編寫的:任何變量、函數、數據結構,在編譯過程中,都會被編譯器安排了一個內存地址,這個地址就是虛擬地址。

 

Q2:虛擬內存的好處?

A2:好處是:編譯器在生成可執行程序時,可以更加自由的分配:代碼中變量的內存地址,不用關心它在實際運行環境中,應該是多少?也不用關心運行環境的內存是否夠用。

相同的 exe文件,同時運行2次,也不用擔心它們同名的變量或函數,會在內存中重疊在一起。因為它們都用的是虛擬地址,無論外表多么相似,都可能被分配在不同的“物理地址”上。

此外,當程序所需的內存大于計算機的實際內存時,虛擬內存機制可以用硬盤來給內存“擴容”。

 

Q3:我電腦的內存有8GB,那跑在該電腦上的程序,其虛擬地址空間,也只能有8GB嗎?

A3:虛擬地址的空間大小,取決于CPU的位數,32位CPU對應的虛擬地址空間為:0~0xFFFFFFFF(4GB),64位CPU對應的虛擬地址空間為:0~0xFFFFFFFFFFFFFFFF(16384PB),它們跟真實的物理內存大小,沒有關系。

 

Q4:為什么我執行實例代碼的時候,輸出的 a 的內存地址總是在變化?

A4:新版本的linux對虛擬內存進行了保護,作了隨機化處理,為了達到文章所述的效果,需要取消這種隨機化處理。請在運行程序之前,在命令行中輸入如下命令:

echo 0 > /proc/sys/kernel/randomize_va_space

分享到:
標簽:虛擬內存
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定