国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【Linux從入門到精通】進程地址空間(虛擬地址 vs 物理地址)

這篇具有很好參考價值的文章主要介紹了【Linux從入門到精通】進程地址空間(虛擬地址 vs 物理地址)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

【Linux從入門到精通】進程地址空間(虛擬地址 vs 物理地址)??

? 本篇文章會圍繞三個問題(什么是地址空間?地址空間是如何設計的?為什么要有地址空間?)進行展開講述。其中主要是了解虛擬地址和物理地址的區(qū)別。希望本篇文章會對你有所幫助。

文章目錄

一、什么是地址空間?

1、1 驗證地址空間

1、2 地址空間是指的物理內(nèi)存嗎?

1、3 地址空間解釋

二、進程訪問地址

2、1 歷史的程序尋址

2、2 進程地址空間映射到物理內(nèi)存

2、3 解釋相同地址打印出不同數(shù)據(jù)

三、為什么要有地址空間

3、1 保護物理內(nèi)存

3、2 內(nèi)存管理和進程管理完成解耦合

3、3 將無序的物理內(nèi)存有序化

四、總結


???♂??作者:@Ggggggtm????♂?

???專欄:Linux從入門到精通? ??

???標題:進程地址空間??

????寄語:與其忙著訴苦,不如低頭趕路,奮路前行,終將遇到一番好風景?????

【Linux從入門到精通】進程地址空間(虛擬地址 vs 物理地址)

一、什么是地址空間?

? ?什么是地址空間呢?我們在學C語言時,經(jīng)常說到程序的變量存儲在棧區(qū)、靜態(tài)區(qū)

堆區(qū)等。這些綜合起來就是地址空間。通俗來講,地址空間就是表示計算機系統(tǒng)中內(nèi)存的總體范圍。它是可用于存儲和訪問數(shù)據(jù)的內(nèi)存地址的集合。

1、1 驗證地址空間

? 我們了解地址空間后,不妨來驗證一下我們之前所學的是否正確。我們之前學的地址空間如下圖:

【Linux從入門到精通】進程地址空間(虛擬地址 vs 物理地址)??

? 我們通過下段代碼來驗證我們之前所學的是否正確:

#include <stdio.h>    
#include <unistd.h>    
#include <stdlib.h>    
    
int g_unval;    
int g_val = 100;    
    
    
int main(int argc, char *argv[], char *env[])    
{    
   // int a = 10;    
    //字面常量    
   const char *str = "helloworld";    
   // 10;    
   // 'a';    
    printf("code addr: %p\n", main);    
    printf("init global addr: %p\n", &g_val);    
    printf("uninit global addr: %p\n", &g_unval);    
    
    char *heap_mem = (char*)malloc(10);    
    char *heap_mem1 = (char*)malloc(10);    
    printf("heap addr: %p\n", heap_mem); //heap_mem(0), &heap_mem(1)    
    printf("heap addr: %p\n", heap_mem1); //heap_mem(0), &heap_mem(1)    
                                                                                                                                                             
    printf("stack addr: %p\n", &heap_mem); //heap_mem(0), &heap_mem(1)    
    printf("stack addr: %p\n", &heap_mem1); //heap_mem(0), &heap_mem(1)    
    
    printf("read only string addr: %p\n", str);    
    int i;    
    for(i = 0 ;i < argc; i++)
    {
        printf("argv[%d]: %p\n", i, argv[i]);
    }
    for(i = 0; env[i]; i++)
    {
        printf("env[%d]: %p\n", i, env[i]);
    }

    return 0;
}

? 上述代碼就有我們所熟知的不同存儲區(qū),我們再來看運行結果:

【Linux從入門到精通】進程地址空間(虛擬地址 vs 物理地址)

? 上圖正是在Linux下運行的結果。在windows下運行的結果所得出的結論也是相同的。我們看到上圖的運行結果后是符合我們所學的地址空間的規(guī)律。

? 棧和堆之間有大量空間是空著的。其次堆和棧是相向而生的。細心的小伙伴可能發(fā)現(xiàn),總共的內(nèi)存空間是4G,而用戶空間只占用3G,那剩下的1G呢?其實完整的地址空間如下:

【Linux從入門到精通】進程地址空間(虛擬地址 vs 物理地址)

1、2 地址空間是指的物理內(nèi)存嗎?

? 我們之前在學C語言時,經(jīng)常會提到 ‘‘地址’等詞匯。例如,我們隨查看的臨時變量所存儲的地址。那么我們經(jīng)常所說的這些地址是指的物理內(nèi)存(物理內(nèi)存是指由于安裝內(nèi)存條而獲得的臨時儲存空間。主要作用是在計算機運行時為操作系統(tǒng)和各種程序提供臨時儲存。)中的地址嗎?

? 答案不確定時,我們看看如下代碼:

#include <stdio.h>    
#include <unistd.h>    
#include <stdlib.h>    
int g_val = 10;    
int main()    
{    
   pid_t id = fork();    
   if(id < 0){    
     perror("fork");    
     return 0;    
   }    
   else if(id == 0){ //child,子進程肯定先跑完,也就是子進程先修改,完成之后,父進程再讀取    
     while(1)    
     {    
      printf("child[%d]: %d : %p\n", getpid(), g_val, &g_val);    
      sleep(1);    
     }    
    
   }else{ //parent    
     while(1)    
     {    
      printf("parent[%d]: %d : %p\n", getpid(), g_val, &g_val);    
      sleep(1);                                                                                                                                              
      g_val=100;    
     }    
   }    
   sleep(1);    
   return 0;    
}   

? 上述代碼就是區(qū)分父子進程,打印同一個變量的值。結果如下圖:

【Linux從入門到精通】進程地址空間(虛擬地址 vs 物理地址)

? 我們驚奇的發(fā)現(xiàn),同一個變量(地址是相同的),他們的值竟然不一樣!難道是一個變量可以存儲兩個不同的值的原因嗎?答案是不是的。

? 我們知道物理內(nèi)存中的地址表示唯一一塊空間,那上述的運行結果證明了,我們所說的地址空間并不是物理地址的!而是存儲在虛擬地址(虛擬內(nèi)存是計算機系統(tǒng)內(nèi)存管理的一種技術。它使得應用程序認為它擁有連續(xù)可用的內(nèi)存,它通常是被分隔成多個物理內(nèi)存碎片,還有部分暫時存儲在外部磁盤存儲器上,在需要時進行數(shù)據(jù)交換)中。?

1、3 地址空間解釋

? 地址空間本質就是一種內(nèi)核數(shù)據(jù)結構,在Linux當中,叫做struct mm_struct(linux內(nèi)核當中的地址空間結構體)包含了一些區(qū)域信息(先描述),能夠實現(xiàn)區(qū)域劃分(本質就是在一定的范圍內(nèi)定義start和end)。??

struct mm_struct
{
    unsigned long code_start;
    unsigned long code_end;
    
    unsigned long init_start;
    unsigned long init_end;
    
    unsigned long uninit_start;
    unsigned long uninit_end;
    
    unsigned long heap_start;
    unsigned long heap_end;
    
    unsigned long stack_start;
    unsigned long stack_end;
    //...等不同的區(qū)域劃分
}

? ?每個進程都會有自己的地址空間,同時進程控制塊(PCB)中也包含了 *mm_struct 指針,可使我們直接找到自己所對應的進程地址空間(后組織)。

? 上述講述的這么多,我們可以理解為進程地址空間就是操作系統(tǒng)給進程花了一個大餅。

? 這個大餅就是指的每個進程都會有4GB的連續(xù)的空間(0x00000000~0xFFFFFFFF)。實際上呢,這4GB的的空間是虛擬內(nèi)存,虛擬內(nèi)存對應的實際物理內(nèi)存,可能只對應的分配了一點點的物理內(nèi)存,實際使用了多少內(nèi)存,就會對應多少物理內(nèi)存。

??這4G虛擬內(nèi)存是一個連續(xù)的地址空間(這也只是進程認為),而實際上,它的數(shù)據(jù)是存儲在多個物理內(nèi)存碎片的,還有一部分存儲在外部磁盤存儲器上,在需要時將數(shù)據(jù)交換進物理內(nèi)存。

二、進程訪問地址

2、1 歷史的程序尋址

? 在虛擬地址出現(xiàn)之前,程序的尋址都是直接尋找的物理地址。但是這樣會有很多的不足:

  1. 直接訪問物理內(nèi)存不安全。例如我們假如使用了野指針,對內(nèi)存中的數(shù)據(jù)進行了修改,那么這個時就會影響到其他的進程;
  2. 因為物理內(nèi)存是有限的,當有多個進程要執(zhí)行的時候,對每個進程都要分配4G內(nèi)存,很顯然你內(nèi)存若小一點,這很快就分配完了,于是沒有得到分配資源的進程就只能等待。當一個進程執(zhí)行完后,再將等待的進程裝入內(nèi)存。這種頻繁的裝入內(nèi)存的操作是很沒效率的。
  3. 因為內(nèi)存是隨機分配的,所以程序運行的地址也是不正確的。

? 由于上述的三個直接原因,后來就產(chǎn)生了虛擬地址。

2、2 進程地址空間映射到物理內(nèi)存

? 當有了虛擬內(nèi)存的概念后,上述的問題就得到了很好的解決。當我們訪問物理內(nèi)存中的數(shù)據(jù)時,需要先訪問進程地址空間上的地址。然后把虛擬地址空間上的地址通過頁表映射到對應的物理內(nèi)存上。具體如下圖:

【Linux從入門到精通】進程地址空間(虛擬地址 vs 物理地址)

? ?地址空間和頁表是每個進程都獨有的一份,只要保證每一個進程的頁表,能夠映射到不同區(qū)域的物理內(nèi)存,就能夠做到進程之間互不干擾。這就是我們所說的進程所具有獨立性。

? 映射是由誰來完成的呢?答案是操作系統(tǒng)!操作系統(tǒng)通過地址轉換機制將虛擬地址映射到物理地址,以實現(xiàn)對內(nèi)存的訪問。這種映射通常在頁表或段表等數(shù)據(jù)結構上實現(xiàn),其中存儲了虛擬地址與物理地址之間的映射關系。?

2、3 解釋相同地址打印出不同數(shù)據(jù)

? 我們在上述的 1、2 中看到了相同的地址打印出不同的數(shù)據(jù)。注意,我們所訪問到的地址都是虛擬地址。并不是物理地址。在上述的 1、2 中我們創(chuàng)建了一個子進程,子進程本身是繼承了父進程的數(shù)據(jù)和代碼。在沒有對數(shù)據(jù)進行修改之前,子進程和父進程共享了一份數(shù)據(jù)。一但對子進程或者父進程的數(shù)據(jù)進行修改,就會發(fā)生寫時拷貝。對修改的數(shù)據(jù)進行深拷貝,從而達到對彼此不產(chǎn)生干擾,實現(xiàn)進程獨立性。

? 那就對相同地址打印出不同數(shù)據(jù)的現(xiàn)象不難理解了。當我們對父進程的數(shù)據(jù)進行修改時,父進程發(fā)生了寫時拷貝,在內(nèi)存中開辟了空間。但他們都有自己的地址空間(虛擬地址),所以地址相同也是正?,F(xiàn)象(子進程繼承父進程的代碼和數(shù)據(jù))。即使虛擬地址一樣,但是可通過頁表映射到不同的物理內(nèi)存中。具體如下圖:

【Linux從入門到精通】進程地址空間(虛擬地址 vs 物理地址)

三、為什么要有地址空間

3、1 保護物理內(nèi)存

? 可能還有一些疑惑:即使有了虛擬地址,那我要是對野指針進行了訪問修改,頁表對野指針映射后,還不是對物理內(nèi)存進行了非法的訪問修改嗎?地址空間的設置不就多此一舉了嗎?

? 事實并非上述一樣。凡是非法的訪問或者映射,操作系統(tǒng)都會識別到的。一但你進行了非法的訪問或者映射,操作系統(tǒng)就會終止掉你的程序。舉個例子,當我們對野指針進行訪問修改時,你的程序就會崩潰,這不就是程序終止退出嗎!??!

? 地址空間有效的保護了物理內(nèi)存。因為地址空間和頁表是操作系統(tǒng)創(chuàng)建并且維護的。這也就意味著地址空間和頁表進行映射時需要操作系統(tǒng)進行監(jiān)管!

3、2 內(nèi)存管理和進程管理完成解耦合

? 因為有了地址空間和頁表,所以我們的數(shù)據(jù)可以在物理內(nèi)存中的任何合法位置加載。因為他們之間有映射。物理內(nèi)存的分配和進程的管理可以做到?jīng)]有關系!

? 所以進程模塊和內(nèi)存模塊只需要各自完成各自的事情,最后通過頁表的映射將他們連接起來,產(chǎn)生關系。降低了他們之間互相的影響度。

【Linux從入門到精通】進程地址空間(虛擬地址 vs 物理地址)

3、3 將無序的物理內(nèi)存有序化

? 由于數(shù)據(jù)可以在物理內(nèi)存中理論上可以加載任何位置,那么是不是物理內(nèi)存中幾乎所有的數(shù)據(jù)和代碼在內(nèi)存中都是亂序的。

? 但是,也為頁表的存在,它可以將地址空間上的虛擬地址和物理地址進行映射,那么在進程的視角所有內(nèi)存分布就是有序的!

四、總結

? 我們平常所訪問到的地址均為虛擬地址。地址空間并不是物理地址,而是虛擬地址。通過頁表映射訪問物理地址。?每個進程都有自己的地址空間和頁表。

? 頁表是一種數(shù)據(jù)結構,它存儲了虛擬地址與物理地址之間的映射關系。在進行地址轉換時,操作系統(tǒng)根據(jù)進程的頁表查找對應的物理地址,然后將虛擬地址轉換為物理地址,以便進行實際的內(nèi)存訪問。

? 通過使用虛擬地址,操作系統(tǒng)可以為每個進程提供獨立的地址空間,使得多個進程可以并發(fā)運行,彼此之間相互隔離,互不干擾。虛擬地址還提供了更高的靈活性和保護性,使得操作系統(tǒng)可以有效地管理和分配內(nèi)存資源,提高系統(tǒng)的性能和安全性。文章來源地址http://www.zghlxwxcb.cn/news/detail-499037.html

到了這里,關于【Linux從入門到精通】進程地址空間(虛擬地址 vs 物理地址)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉載,請注明出處: 如若內(nèi)容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

  • Linux內(nèi)存管理 | 四、物理地址空間設計模型

    Linux內(nèi)存管理 | 四、物理地址空間設計模型

    我的圈子: 高級工程師聚集地 我是董哥,高級嵌入式軟件開發(fā)工程師,從事嵌入式Linux驅動開發(fā)和系統(tǒng)開發(fā),曾就職于世界500強企業(yè)! 創(chuàng)作理念:專注分享高質量嵌入式文章,讓大家讀有所得! 前面幾篇文章,主要講解了虛擬內(nèi)存空間的布局和管理,下面同步來聊聊物理內(nèi)

    2024年02月08日
    瀏覽(21)
  • 【Linux】程序地址空間?進程地址空間

    【Linux】程序地址空間?進程地址空間

    了解進程的運行: ?運行結果:我們會發(fā)現(xiàn)這打印的結果亂七八糟,因為它也不知道什么時候該干什么 ?我們讓代碼睡眠1秒:打印的結果就正常了 ?以前我們學習的內(nèi)存管理(程序地址空間): ?為了驗證上面虛擬地址,我們運行下面代碼: (這種問題出現(xiàn)的原因在下面的為

    2024年02月13日
    瀏覽(21)
  • Linux: 進程地址空間究竟是什么?進程地址空間存在意義何在?

    Linux: 進程地址空間究竟是什么?進程地址空間存在意義何在?

    ?在C/C++中,我們常將內(nèi)存分為: 代碼區(qū)、常量區(qū)、全局區(qū)(靜態(tài)區(qū))、堆、棧 等等。相關內(nèi)存區(qū)域劃分如下:(X86, 32位平臺) 如何驗證C/C++中各區(qū)域的相對位置呢? ?我們可以在每個區(qū)域中選擇一個地址來驗證C/C++中各區(qū)域的相對位置??!具體如下: 【源代碼】: 【運行

    2024年04月08日
    瀏覽(26)
  • Linux之進程(四)(進程地址空間)

    Linux之進程(四)(進程地址空間)

    目錄 一、程序地址空間 二、進程地址空間 1、概念 2、寫時拷貝 3、為什么要有進程地址空間 四、總結 我們先來看看下面這張圖。這張圖是我們在學習語言時就見到過的內(nèi)存區(qū)域劃分圖。? 下面我們在Linux下看一看內(nèi)存區(qū)域是不是也是這么劃分的。 可見在Linux下也是符合上面

    2024年02月04日
    瀏覽(23)
  • 【Linux】進程>環(huán)境變量&&地址空間&&進程調度

    【Linux】進程>環(huán)境變量&&地址空間&&進程調度

    主頁: 醋溜馬桶圈-CSDN博客 專欄: Linux_醋溜馬桶圈的博客-CSDN博客 gitee :mnxcc (mnxcc) - Gitee.com 目錄 1.環(huán)境變量 1.1 基本概念 1.2 常見環(huán)境變量? 1.3 查看環(huán)境變量方法? 1.4?和環(huán)境變量相關的命令 1.5 環(huán)境變量的組織方式 1.6 通過代碼如何獲取環(huán)境變量 1.6.1 命令行第三個參數(shù) 1

    2024年04月15日
    瀏覽(28)
  • 【Linux】進程周邊006之進程地址空間

    【Linux】進程周邊006之進程地址空間

    ? ?? 樊梓慕: 個人主頁 ??? 個人專欄: 《C語言》 《數(shù)據(jù)結構》 《藍橋杯試題》 《LeetCode刷題筆記》 《實訓項目》 《C++》 《Linux》 ?? 每一個不曾起舞的日子,都是對生命的辜負 目錄 前言 1.程序地址空間 1.1驗證地址空間的排布 ?1.2利用fork函數(shù)觀察當子進程修改某個共

    2024年02月04日
    瀏覽(43)
  • 【Linux】—— 進程地址空間

    【Linux】—— 進程地址空間

    序言: 在上篇中,我們講解了關于進程優(yōu)先級的概念。本期,我將給大家介紹的是關于進程地址空間的話題。 目錄 (一)程序地址空間回顧 (二)代碼演示 (三)進程地址空間的引入 總結 我們在學習C/C++語言的時候,大家可能都見過這樣的空間布局圖: 一個程序有哪些

    2024年02月15日
    瀏覽(25)
  • 【Linux】深挖進程地址空間

    【Linux】深挖進程地址空間

    作者簡介:?舊言~,目前大二,現(xiàn)在學習Java,c,c++,Python等 座右銘:松樹千年終是朽,槿花一日自為榮。 目標:熟悉【Linux】進程地址空間 毒雞湯:也許有一天,你發(fā)覺日子特別的艱難,那可能是這次的收獲特別的巨大。 望小伙伴們點贊??收藏?加關注喲????? ????

    2024年02月03日
    瀏覽(26)
  • 【Linux】理解進程地址空間

    【Linux】理解進程地址空間

    ?? 作者: 阿潤菜菜 ?? 專欄: Linux系統(tǒng)編程 ?我們在學習C語言的時候,都學過內(nèi)存區(qū)域的劃分如棧、堆、代碼區(qū)、數(shù)據(jù)區(qū)這些。但我們其實并不真正理解內(nèi)存 — 我們之前一直說的內(nèi)存是物理上的內(nèi)存嗎? 我們先看一段測試代碼: 運行結果: 我們可以注意到子進程的變量

    2024年02月02日
    瀏覽(28)
  • Linux:進程地址空間

    Linux:進程地址空間

    目錄 1.程序地址空間? 2.進程地址空間 我們在講C/C++語言的時候,32位平臺下,我們見過這樣的空間布局圖 我們來驗證一下這張圖的正確性: 運行結果: 通過觀察靜態(tài)變量的位置,可以認為靜態(tài)變量就是全局變量,只是靜態(tài)變量只初始化一次,有作用域的限制。 這里棧區(qū)還

    2024年02月04日
    瀏覽(28)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包