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

【Linux】地址空間&&虛擬地址

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

個人主頁 : zxctscl
如有轉(zhuǎn)載請先通知

1. 虛擬地址

1.1 虛擬地址引入

先先來一個測試代碼:

  1 #include<stdio.h>
  2 #include<unistd.h>
  3 #include<string.h>
  4 #include<stdlib.h>
  5
  6 int g_val=100;
  7
  8 int main()
  9 {
 10   printf("father is running,pid:%d,ppid:%d\n",getpid(),getppid());
 11
 12
 13   pid_t id=fork();
 14   if(id==0)
 15   {
 16     int cnt=0;
 17     while(1)
 18     {
 19     printf("I am child process,pid:%d,ppid:%d,g_val:%d,&g_val:%p\n",getpid(),getppid(),g_val,&g_val);
 20     sleep(1);
 21     cnt++;
 22     if(cnt==5)
 23     {
 24       g_val=300;
 25       printf("I am child process,change %d->%d\n",100,300);
 26     }
 27     }
 28   }
 29   else{
 30     while(1)
 31     {
 32     printf("I am father process,pid:%d,ppid:%d,g_val:%d,&g_val:%p\n",getpid(),getppid(),g_val,&g_val);
 33     sleep(1);
 34   }
 35
 36 }
 37 }
 38

編譯運行:
子進程把數(shù)據(jù)改了,父進程的數(shù)據(jù)沒有改變,但是父子地址是一樣的。
【Linux】地址空間&&虛擬地址,Linux從入門到入土,linux,運維,服務(wù)器,c語言

這個地址絕對不是物理地址,理論上修改了數(shù)據(jù)為300之后不可能在輸出有100,訪問一個地址怎么可能又是100也是300。這個地址在系統(tǒng)層面上稱之為虛擬地址。

1.2 虛擬地址理解

每一個進程除了要把代碼和數(shù)據(jù)加載到內(nèi)存之外,對于當(dāng)前的操作系統(tǒng)來講,系統(tǒng)當(dāng)中會為每一個進程創(chuàng)建一個地址空間。

地址空間在操作系統(tǒng)里面。在32位和64位下的地址空間大小是不一樣的,為了方便這里使用32位來表述。32位從低到高一個有4GB的地址空間范圍,實際上這個地址空間當(dāng)中打印出來的地址,是該空間內(nèi)對應(yīng)的地址。進程是可以指向這個地址空間的。

【Linux】地址空間&&虛擬地址,Linux從入門到入土,linux,運維,服務(wù)器,c語言
其實PCB和地址空間都是在物理內(nèi)存里面的,只不過要訪問初始化全局數(shù)據(jù)的時候,不在地址空間上保存,地址空間只會提供線性連續(xù)地址,讓用戶之后通過虛擬地址的地址空間,將虛擬地址轉(zhuǎn)化到為了物理內(nèi)存中。
此時計算機的體系結(jié)構(gòu)中還存在一個頁表,頁表它的主要功能是負責(zé)將地址空間中的虛擬地址和物理地址之間建立映射關(guān)系。未來在用進程進行訪問的時候,操作系統(tǒng)會自動用虛擬地址查頁表轉(zhuǎn)換為物理地址,然后讓用戶訪問到數(shù)據(jù)。

【Linux】地址空間&&虛擬地址,Linux從入門到入土,linux,運維,服務(wù)器,c語言
父進程的代碼可以通過頁表地址映射轉(zhuǎn)換到為了內(nèi)存中代碼,父進程通過連續(xù)的地址空間就可以訪問到它的代碼和數(shù)據(jù)。

【Linux】地址空間&&虛擬地址,Linux從入門到入土,linux,運維,服務(wù)器,c語言
假設(shè)在物理內(nèi)存上存放一個全局變量g_val,默認內(nèi)容是100,g_val在頁表在地址空間中都要被找到,所以在地址空間的初始化數(shù)據(jù)中就有它的地址虛擬地址,頁表的左側(cè)也有它的虛擬地址,在頁表右側(cè)就有它對應(yīng)的物理地址。
【Linux】地址空間&&虛擬地址,Linux從入門到入土,linux,運維,服務(wù)器,c語言

當(dāng)創(chuàng)建了一個子進程,本質(zhì)上是系統(tǒng)多了一個進程,它也有自己的task_truct,還有自己的虛擬地址空間,還有它所對應(yīng)的頁表。

每個進程都要有自己的虛擬的地址空間,也要有自己對應(yīng)的頁表。
每個進程都要有自己獨立的地址空間,那么操作系統(tǒng)就得管理很多個進程的地址空間,而地址空間本質(zhì)上就是內(nèi)核中的一個數(shù)據(jù)結(jié)構(gòu)對象。

子進程會把父進程的很多數(shù)據(jù)結(jié)構(gòu)全拷貝一份,基本上子進程的PCB、地址空間和頁表基本上和父進程的一致。
子進程的地址空間也會有一個虛擬地址,子進程對應(yīng)的頁表也來自父進程,所以頁表保存的地址,從而子進程也會指向那個g_val。
【Linux】地址空間&&虛擬地址,Linux從入門到入土,linux,運維,服務(wù)器,c語言

所以子進程和父進程看到的虛擬地址是一樣的,并且它們的頁表也一樣,指向的物理內(nèi)存也一樣,所以它們打印出來的地址也就是相同的了。

如果子進程進行寫入,也是通過頁表向物理內(nèi)存處進行寫入,寫入的時候直接找到g_val把100改為300。可子進程一旦對數(shù)據(jù)做修改了,父進程就會看到。如果子進程直接修改了數(shù)據(jù),就會導(dǎo)致程序運行本身問題。
而進程本身在運行的時候具有獨立性,所以子進程對數(shù)據(jù)進行修改,就不能影響到父進程,所以當(dāng)子進程嘗試對數(shù)據(jù)進行修改時,操作系統(tǒng)發(fā)現(xiàn)父進程也有,就在在子進程修改之前,在物理內(nèi)存中出現(xiàn)開辟一個空間,開辟完成之后。然后把修改之前的數(shù)據(jù)拷貝到新空間中,再把新的物理地址和之前的物理地址相比較,把新的物理地址放在子進程的頁表中,重新構(gòu)建映射,頁表的右側(cè)就指向新的物理地址空間,這個工作結(jié)束,才會就行讓子進程執(zhí)行寫入操作,把100改為300。
【Linux】地址空間&&虛擬地址,Linux從入門到入土,linux,運維,服務(wù)器,c語言
重新開辟物理內(nèi)存這些都是操作系統(tǒng)自己做,上面這個過程叫做寫時拷貝。

修改的只是子進程的物理地址和頁表,而地址空間里面的依然是虛擬地址。子進程和父進程的虛擬地址是一樣的,只是映射到物理內(nèi)存到不同區(qū)域,所以對應(yīng)看到的地址是一樣的,但內(nèi)容卻不一樣。

1.3 虛擬地址細節(jié)問題

如果父子進程不寫,未來一個全局變量,默認是被父子共享的,代碼(只讀)是共享的。

為什么會存在寫時拷貝?
因為進程具有獨立性,所以父子進程有自己的地址空間和頁表。
但是代碼是共享的,那么怎么不在創(chuàng)建子進程的時候,全部給子進程拷貝一份?
主要是在父進程中的數(shù)據(jù)子進程不一定都會修改,而這些占據(jù)的空間又很大,子進程程序拷貝一份就是在浪費空間,所以采用寫時拷貝,就是為了按需申請。必須寫時才能拷貝是為了保證進程的獨立性。
按需申請本質(zhì)是通過調(diào)整拷貝時間順序,達到有效節(jié)省空間的目的。

2. 地址空間

2.1 理解地址空間

地址空間本質(zhì)是內(nèi)核的一個struct結(jié)構(gòu)體,結(jié)構(gòu)體里面有各種各樣的區(qū)域劃分,內(nèi)部有很多的屬性都是表示start,end的范圍。
來看看源碼里面描寫這個結(jié)構(gòu)體:
【Linux】地址空間&&虛擬地址,Linux從入門到入土,linux,運維,服務(wù)器,c語言
并不是限定了某一個范圍,而是這個范圍之間它所對應(yīng)地址空間都可以使用。這個范圍可以根據(jù)頁表映射到物理內(nèi)存。

操作系統(tǒng)給每一個進程都劃分一塊進程地址空間。
【Linux】地址空間&&虛擬地址,Linux從入門到入土,linux,運維,服務(wù)器,c語言
為什么要有地址空間?
一個程序的代碼和數(shù)據(jù)放在物理內(nèi)存中,如果沒有虛擬地址空間,要直接找到程序的代碼和數(shù)據(jù),就必須讓進程的PCB把對應(yīng)的代碼和數(shù)據(jù)都記錄下來。如果當(dāng)前還有其他程序,都在物理內(nèi)存中,每一個程序都在物理內(nèi)存中加載的話,也就要求每一個進程所對應(yīng)的代碼和數(shù)據(jù)在物理內(nèi)存的哪一個位置都得記錄下來。這個記錄對應(yīng)進程而言負擔(dān)是比較大的,也就是進程直接使用物理地址。
【Linux】地址空間&&虛擬地址,Linux從入門到入土,linux,運維,服務(wù)器,c語言
就有可能出現(xiàn)訪問越界,或者訪問到其他進程的代碼和數(shù)據(jù)。所以用進程記錄物理地址就比較混亂,不利于做統(tǒng)一管理。
實際物理內(nèi)存中的代碼區(qū),數(shù)據(jù)區(qū)、堆區(qū)、棧區(qū)、共享區(qū)、命令行參數(shù)和環(huán)境變量,對一個進程來講可能是亂序的,那么再加載其他進程也是亂序的。

進程在申請內(nèi)存時,在地址空間上能申請就可以,在頁表對應(yīng)的左側(cè)就可以了,右側(cè)可以先不填,當(dāng)用戶真正用到的時候在申請。

地址空間和也表存在的好處就是:一、將無序變有序,讓進程以統(tǒng)一的視角來看待物理內(nèi)存以及自己運行的各個區(qū)域
二、進程管理模塊和內(nèi)存管理模塊進行解耦

地址空間并不是百分百使用的,一般只使用一部分。比如在堆區(qū),申請了五十個字節(jié),可是遍歷的時候計數(shù)器越界了,在地址空間里面就越界了,操作系統(tǒng)就直接攔截了這個請求,所有的非法請求都不能通過地址空間到物理內(nèi)存上,也就是保護物理內(nèi)存。
攔截非法請求就是對物理內(nèi)存進行保護

2.2 頁表和寫時拷貝

【Linux】地址空間&&虛擬地址,Linux從入門到入土,linux,運維,服務(wù)器,c語言

查頁表對內(nèi)存地址進行訪問是CPU,它里面包含CR3寄存器內(nèi),CPU的還有有一個叫做MMU硬件(內(nèi)存管理單元),快速把虛擬地址結(jié)合頁表轉(zhuǎn)化為物理地址。
頁表里面的一些選項來支持權(quán)限管理。就像是C語言中不能修改字符常量區(qū),是因為頁表里面沒有給修改的權(quán)限。

【Linux】地址空間&&虛擬地址,Linux從入門到入土,linux,運維,服務(wù)器,c語言
操作系統(tǒng)支持寫時拷貝,頁表給父進程的權(quán)限是rw。當(dāng)父進程創(chuàng)建子進程之后,子進程的頁表權(quán)限是r。當(dāng)父進程一旦創(chuàng)建子進程,父進程為了支持寫時拷貝,因為父進程走到已初始化全局區(qū)本來就是可以寫的,但創(chuàng)建子進程之后,操作系統(tǒng)會直接修改頁表中該位置的權(quán)限,都修改為r。當(dāng)父子進程中任何一個嘗試寫入時,此時系統(tǒng)就會直接識別到錯誤。
操作系統(tǒng)識別到錯誤就得判斷:1.是不是數(shù)據(jù)不在物理內(nèi)存;2.是不是數(shù)據(jù)想要寫時拷貝;3.如果都不是,才能進行異常處理。
第一種解決就是缺頁中斷,第二種就發(fā)生寫時拷貝。
【Linux】地址空間&&虛擬地址,Linux從入門到入土,linux,運維,服務(wù)器,c語言
上面的圖就足矣說名問題,同一個變量,地址相同,其實是虛擬地址相同,內(nèi)容不同其實是被映射到了不同的物理地址!

【Linux】地址空間&&虛擬地址,Linux從入門到入土,linux,運維,服務(wù)器,c語言
在最開始的時候,地址空間的頁表里面的數(shù)據(jù)從哪里來?
程序一旦加載到內(nèi)存就有地址。程序在變成二進制的時候本身就有地址。也就是說程序里面本身就有地址。
【Linux】地址空間&&虛擬地址,Linux從入門到入土,linux,運維,服務(wù)器,c語言
來看一下之前的代碼:

  1 #include<stdio.h>
  2 #include<unistd.h>
  3 #include<string.h>
  4 #include<stdlib.h>
  5
  6
  7 int main()
  8 {
  9   pid_t id=fork();
 10   if(id==0)
 11   {
 12     while(1)
 13     {
 14       printf("child,%d,%p\n",id,&id);
 15       sleep(1);
 16     }
 17   }
 18   else if(id>0)
 19   {
 20     while(1)
 21     {
 22       printf("father,%d,%p\n",id,&id);
 23       sleep(1);
 24     }
 25    }
 26   return 0;
 27   }
 28

當(dāng)fork()時候,不管是父進程還是子進程,都要return。在return時候,本質(zhì)就是對id進行寫入,而id本身是父進程定義的變量,不論是父進程還是子進程,誰先return,都得return兩次,進程在return的時候,發(fā)生寫時拷貝。所以當(dāng)父進程用id的時候,它認為id大于0;子進程在返回的時候它認為id等于0。所以虛擬地址相同而物理地址不同。

3. 進程調(diào)度

Linux中的nice值并不是能任意調(diào)度的,而是從-20到19,這40個數(shù)字之間變換。

在操作系統(tǒng)中每一個CPU都會有一個運行隊列:
【Linux】地址空間&&虛擬地址,Linux從入門到入土,linux,運維,服務(wù)器,c語言
來看看藍色區(qū)域的部分,這里面有queue隊列包含140項,它其實是task_struct *queue[140]
queue[140]: 一個元素就是一個進程隊列,相同優(yōu)先級的進程按照FIFO規(guī)則進行排隊調(diào)度,所以,數(shù)組下標(biāo)就是優(yōu)先級!
nr_active: 總共有多少個運行狀態(tài)的進程
【Linux】地址空間&&虛擬地址,Linux從入門到入土,linux,運維,服務(wù)器,c語言
從該結(jié)構(gòu)中,選擇一個最合適的進程,過程是怎么的呢?

  1. 從0下表開始遍歷queue[140]
  2. 找到第一個非空隊列,該隊列必定為優(yōu)先級最高的隊列
  3. 拿到選中隊列的第一個進程,開始運行,調(diào)度完成!
  4. 遍歷queue[140]時間復(fù)雜度是常數(shù)!但還是太低效了!

bitmap[5]:一共140個優(yōu)先級,一共140個進程隊列,為了提高查找非空隊列的效率,就可以用5*32個比特位表示隊列是否為空,這樣,便可以大大提高查找效率!

【Linux】地址空間&&虛擬地址,Linux從入門到入土,linux,運維,服務(wù)器,c語言
活躍進程的task_struct *queue[140]只出不進,過期進程的task_struct *queue[140]只進不出。

active指針和expired指針:active指針永遠指向活動隊列;expired指針永遠指向過期隊列。
可是活動隊列上的進程會越來越少,過期隊列上的進程會越來越多,因為進程時間片到期時一直都存在的。
沒關(guān)系,在合適的時候,只要能夠交換active指針和expired指針的內(nèi)容,就相當(dāng)于有具有了一批新的活動進程!

有問題請指出,大家一起進步?。?!文章來源地址http://www.zghlxwxcb.cn/news/detail-855274.html

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

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

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • 【Linux系統(tǒng)化學(xué)習(xí)】進程地址空間 | 虛擬地址和物理地址的關(guān)系

    【Linux系統(tǒng)化學(xué)習(xí)】進程地址空間 | 虛擬地址和物理地址的關(guān)系

    ========================================================================= 個人主頁點擊直達: 小白不是程序媛 Linux專欄: Linux系統(tǒng)化學(xué)習(xí) 代碼倉庫: Gitee ========================================================================= 目錄 虛擬地址和物理地址 頁表 進程地址空間 進程地址空間存在的意義 我們在學(xué)

    2024年02月05日
    瀏覽(25)
  • 【Linux-14】進程地址空間&虛擬空間&頁表——原理&知識點詳解

    【Linux-14】進程地址空間&虛擬空間&頁表——原理&知識點詳解

    前言 大家好吖,歡迎來到 YY 滴 系列 ,熱烈歡迎! 本章主要內(nèi)容面向接觸過Linux的老鐵 主要內(nèi)容含: 歡迎訂閱 YY 滴C++專欄!更多干貨持續(xù)更新!以下是傳送門! YY的《C++》專欄 YY的《C++11》專欄 YY的《Linux》專欄 YY的《數(shù)據(jù)結(jié)構(gòu)》專欄 YY的《C語言基礎(chǔ)》專欄 YY的《初學(xué)者易

    2024年04月29日
    瀏覽(31)
  • 【看表情包學(xué)Linux】進程地址空間 | 區(qū)域和頁表 | 虛擬地址空間 | 初識寫時拷貝

    【看表情包學(xué)Linux】進程地址空間 | 區(qū)域和頁表 | 虛擬地址空間 | 初識寫時拷貝

    ?? ??? 爆笑 教程 ????《看表情包學(xué)Linux》?? ? 猛戳訂閱 ? ? ?? ?? 寫在前面: 本章核心主題為?\\\"進程地址空間\\\",會通過驗證 Linux 進程的地址空間來開頭,拋出 \\\"同一個值能有不同內(nèi)容\\\" 的現(xiàn)象,通過該現(xiàn)象去推導(dǎo)出 \\\"虛擬地址\\\" 的概念。然后帶著大家理解為什么虛擬地

    2024年01月20日
    瀏覽(19)
  • Linux內(nèi)核源碼分析 (B.2)虛擬地址空間布局架構(gòu)

    Linux內(nèi)核源碼分析 (B.2)虛擬地址空間布局架構(gòu)

    Linux內(nèi)核只是操作系統(tǒng)當(dāng)中的一部分,對下管理系統(tǒng)所有硬件設(shè)備,對上通過系統(tǒng)調(diào)用向 Library Routine 或其他應(yīng)用程序提供API接口。 內(nèi)存管理可以通過以下三個維度進行介紹: 用戶空間 相當(dāng)于應(yīng)用程序使用 malloc() 申請內(nèi)存,通過 free() 釋放內(nèi)存。 malloc() / free() 是 glibc 庫的內(nèi)

    2024年02月09日
    瀏覽(41)
  • [Linux]環(huán)境變量 進程地址空間(虛擬內(nèi)存與物理內(nèi)存的關(guān)系)

    [Linux]環(huán)境變量 進程地址空間(虛擬內(nèi)存與物理內(nèi)存的關(guān)系)

    hello,大家好,這里是bang_bang,今天我們來講一下語言層級上的程序地址空間和系統(tǒng)層級上的進程地址空間的區(qū)別,在下面中我舉的例子會設(shè)計到環(huán)境變量,所以開篇我先講講環(huán)境變量。 目錄 1??環(huán)境變量 ?? 基本概念 ??環(huán)境變量相關(guān)命令 ??查看環(huán)境變量echo ??添加全局環(huán)

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

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

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

    2024年02月13日
    瀏覽(21)
  • Linux:http服務(wù)(Apache 2.4.57)源碼編譯——配置網(wǎng)站 || 入門到入土

    Linux:http服務(wù)(Apache 2.4.57)源碼編譯——配置網(wǎng)站 || 入門到入土

    目錄 1.下載源碼包 2.配置httpd運行環(huán)境 3.編譯源碼包安裝apache軟件 4.優(yōu)化執(zhí)行路徑 5.添加httpd系統(tǒng)服務(wù) #正文 1.httpd服務(wù)器的基本配置 2.Linux命令行訪問網(wǎng)站 3. 網(wǎng)站日志 4.控制網(wǎng)站訪問? 5.創(chuàng)建用戶認證數(shù)據(jù)庫 #構(gòu)建虛擬web主機 1.構(gòu)建虛擬主機——基于域名 2.構(gòu)建虛擬主機——基

    2024年02月15日
    瀏覽(21)
  • Linux:tomcat (源碼包安裝)(官網(wǎng)下載-安裝-啟動-配置-等等等-----從入門到入土)

    Linux:tomcat (源碼包安裝)(官網(wǎng)下載-安裝-啟動-配置-等等等-----從入門到入土)

    Apache Tomcat?軟件是一個開源實現(xiàn)?Jakarta Servlet、Jakarta?Server Pages、Jakarta Expression?Language、Jakarta WebSocket、Jakarta?Annotations?和?Jakarta Authentication?規(guī)范。?這些規(guī)范是Jakarta EE平臺的一部分。 Apache Tomcat軟件是在開放和參與式中開發(fā)的。 環(huán)境,并在?Apache 許可證版本 2?下發(fā)布。這

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

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

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

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

    【Linux】—— 進程地址空間

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

    2024年02月15日
    瀏覽(25)

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

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

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

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

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包