亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Linux進程地址空間詳解

 更新時間:2024年10月04日 10:45:35   作者:??小陳在拼命??  
在C語言編程中,內存管理是一個重要的環(huán)節(jié),本文詳細解析了C語言中的內存區(qū)域劃分,包括棧區(qū)、堆區(qū)、全局區(qū)等,并探討了fork函數的遺留問題,即如何出現(xiàn)一個變量同時等于0又大于0的情況,此外,文章還深入討論了進程地址空間的概念

一、C語言內存管理基礎

引入:以前我們知道一個指針指向的如果是一個常量字符串,那么這個就是指向的常量區(qū),只讀不可被修改,因此下面的程序會崩潰。

1、在我們C語言內存管理機制里面線性地址是有區(qū)域劃分的。

我們如何驗證這個區(qū)域的劃分是否正確呢?

可以通過代碼的方式在不同的區(qū)域創(chuàng)建變量然后來取地址獲取再進行比較

2、棧區(qū)和堆區(qū)是相對而行的??!

驗證棧區(qū):地址在變低

驗證堆區(qū):地址在變高

3、靜態(tài)變量會被定義在全局區(qū) 只不過只會在作用域里使用。

二、fork遺留問題

歷史遺留問題:為什么一個變量可以同時等于0又同時>0 ??

實驗:

我們會發(fā)現(xiàn)同一個地址竟然讀到了不同的內容?。?如果變量的地址是一個物理地址,是絕對不可能出現(xiàn)這種情況的,因此我們的變量地址必然是不是物理地址??!

——>結論:我們平時C/C++里面使用的地址全都不是物理地址,而是虛擬地址! 用戶是看不到物理地址的,而OS必須要負責將我們所看到的虛擬地址轉化成物理地址!

三、進程地址空間

其實我們的之前所學的線性地址,并不是真正的物理內存,而是在PCB內部有一個指針指向了一塊進程地址空間,然后虛擬地址會通過頁表來映射到具體的物理地址。 ——>所以當我們創(chuàng)建出一個子進程后,他會拷貝一份和父進程一樣的地址空間,然后當子進程想要修改對應的數據時,此時就會發(fā)生寫時拷貝(由操作系統(tǒng)自動完成),也就是重新開辟空間,在這個過程當中只有頁表對應的物理地址發(fā)生了變化,左邊的地址空間不會有任何的感知。

3.1 什么叫做地址空間

在32位的機器中,有32位的地址和數據總線,所以每一根地址總線有0或1,其實從本質上來說計算機能夠識別是高低電頻而并非二進制,所以1代表的是高電頻,0代表的是低電頻。——>這個過程就是CPU通過像內存充電的形式告訴內存我需要哪個地址,然后內存就能夠通過識別高低電頻,形成一個物理數據,將地址對應的數據以同樣的方式交給CPU。

所以地址空間就是地址總線排列組合形成的地址的范圍【0,2^32】

3.2 如何理解地址空間的區(qū)域劃分?

舉個例子:比方說當前的桌子有100cm長,坐著小胖和小美,但是小胖經常騷擾小美,所以就在桌子中間畫了一個三八線。 一人只有50cm的空間。所以從結構上就可以如下劃分:

區(qū)域劃分就是通過結構體內部的start和end去做劃分

如何理解區(qū)域的變大或者變小呢??——>修改對應結構體內部的start和end即可

我們不僅要看到地址空間的范圍,我們要知道在范圍內連續(xù)的空間中,每一個最小單位都可以有地址,這個地址可以被直接使用??!

3.3 什么是進程地址空間

所謂進程地址空間,本質上就是一個描述進程可視化范圍的地址空間內存在各種區(qū)域劃分,對線性地址進行start、end即可 。本質上其實就是一個內核數據結構,和PCB一樣,地址空間也是需要被/操作系統(tǒng)管理的:先描述再組織。 而每一個進程都有自己的進程地址空間,PCB內部有一個指針指向這塊空間!

四、頁表

共識:現(xiàn)代操作系統(tǒng)中,幾乎不做浪費空間和時間的事情!

4.1 寫時拷貝、缺頁中斷、惰性加載

頁表具體有哪些內容呢??——>虛擬地址、物理地址、讀寫權限、標志位(對應的代碼和數據是否被加載到內存中)

讀寫權限就可以幫助我們做檢查,比方說當前是常量字符區(qū)但是你卻想修改,就會被/操作系統(tǒng)攔截,該非法請求就不會被發(fā)送到物理內存。

標志位就是幫助們判斷進程的代碼和數據是否被加載到內存中,因為我們知道我們的進程對應的代碼和數據是有可能處于掛起狀態(tài)的(還沒加載到內存)。

惰性加載:其實就是需要多少就加載多少。操作系統(tǒng)對大文件是可以實現(xiàn)分批加載,也就是說當前的進程可能只有PCB在內存中,但是代碼和數據可能還沒馬上加載進來。

缺頁中斷:在執(zhí)行進程的時候如果發(fā)現(xiàn)標記位顯示當前代碼和數據沒有加載起來,就會發(fā)生缺頁中斷,也就是暫時中斷這個進程,然后等代碼和數據加載進來之后,再恢復原來的狀態(tài)繼續(xù)運行。

問題:一次加載進去不是更快嗎,為什么需要檢測了之后才通過缺頁中斷加載進去??

——> 一方面是因為可能這個文件特別大,所以沒辦法一次加載進去,就算是可以一次加載進去,可是你用不也是一點點去用么?? 所以缺頁中斷解決的是初步局部性加載的問題,能夠更合理的去使用內存!!

寫時拷貝:數據區(qū)的數據是按道理是可寫的,但是一開始權限會被設置成只讀(意思就是當前父子進程共享),一旦父子進程任意一方嘗試做修改的時候,發(fā)現(xiàn)當前的數據是只讀的(但是這里不做異常處理,而是轉而發(fā)生寫時拷貝),然后開辟一塊新的物理內存,修改頁表的映射

4.2 進程地址空間是如何切換的

進程PCB結構體里有對應的進程地址空間指針,所以進程切換就以為這進程空間地址空間被切換,而頁表會被存儲在CPU的cr3寄存器中,這其實屬于進程的上下文信息,在進程切換的時候會被進程帶走,后面再恢復過來??!

4.3 進程創(chuàng)建的具體過程分析

進程被創(chuàng)建的時候,優(yōu)先加載的是PCB結構體以及里面對應的進程地址空間結構體,然后他的代碼和數據可能不會馬上被加載進來。

4.4 再次理解進程具有獨立性

1、在內核數據結構上是獨立的

2、物理內存中加載的代碼和數據,只需要再頁表上去體現(xiàn)。虛擬地址可以一樣,但是通過頁表映射不同的物理地址,就可以讓父子進程解耦,一旦發(fā)生了任何異常,你釋放你的我釋放我的。

3、通過頁表的虛擬地址映射物理地址,可以隨便取地址,甚至是亂序。但是虛擬地址可以將一個線性的地址呈現(xiàn)給進程。

五、為什么要有進程地址空間?(重點)

所以我們可以對進程進行一個再總結:

講個故事1:

一個大富翁(操作系統(tǒng))有10億美金,而他有四個私生子,但是四個私生子(進程)都并不知道對方的存在,所以他們都認為大富翁只有他唯一一個兒子,而大富翁告訴他們一旦自己去世了,就把所有的家產留給他,所以每個兒子也都信了,所以大富翁其實給每個私生子都畫了一個大餅(進程地址空間)。每個人都認為自己有十億家產。 但實際上是這些私生子要多少才會給多少(進程需要多少空間操作系統(tǒng)就給多少空間)

結論1:讓進程以統(tǒng)一的視角看待內存 這樣我進程就不需要關心說具體應該放在物理內存的什么位置,也不需要關心當前這個物理內存是否會影響別人的數據,這些工作都由操作系統(tǒng)去完成。

故事2:

你過年的時候經常有壓歲錢,但是你還小所以你經常會買到一些沒有用的東西,于是你的媽媽就讓你把錢交給他保管,等你需要買什么的時候,他再把錢給你,比如說當你想要買個一塊錢的橡皮時,你媽媽就給了你一塊錢,但如果你想花100塊錢買個游戲機的時候,你的媽媽就不給你買,所以這個過程其實媽媽的作用就是會阻止你做一些不太適合的事情。

結論2:增加虛擬地址空間,可以讓我們訪問的時候增加一個轉換的過程,在這個轉化的過程中我們可以對我們的尋址進行審查,所以一旦異常訪問,直接攔截,該請求就不會到達物理內存,從而保護物理內存

結論3:因為有地址空間和頁表的存在,將進程管理模塊和內存模塊進行解耦合 !

申請物理內存的哪一塊?優(yōu)先加載可執(zhí)行程序的哪一部分??又或者頁表填寫到什么地方??這是有Linux的內存模塊去管理的,進程并不需要關心。

結論4:其實變量名在定義的時候就已經被轉化成一個個虛擬地址了,而我們之所以有a和&a,本質上是為了區(qū)分想獲取的是變量的值還是地址。

結論5:以前我們所學習的C內存管理,其實本質上是進程地址空間,而內存管理是由Linux替我們完成的,我們上層語言并不需要關心具體的細節(jié),只需要正常去通過對應的線性地址去使用就行了。

六、命令行參數和環(huán)境變量在棧的上面

所以環(huán)境變量和命令行參數是在棧之上的一個獨立空間。 所以為什么子進程可以繼承父進程的環(huán)境變量,因為子進程啟動時,父進程已經把對應的環(huán)境變量信息加載進去了, 他也是地址空間的一部分,所以他必然有頁表去幫助我們建立虛擬地址和物理地址的映射,而當子進程創(chuàng)建的時候,子進程也會將父進程虛擬地址空間當中的環(huán)境變量的相關參數也給我們建立了一份映射,所以即使你傳參數,子進程也照樣能夠獲得父進程的環(huán)境變量信息。

我們目前所關注的是用戶空間。

總結

以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關文章

  • Linux系統(tǒng)刪除文件夾和文件的命令

    Linux系統(tǒng)刪除文件夾和文件的命令

    筆者給大家介紹Linux系統(tǒng)刪除文件夾和文件的命令,很多朋友喜歡是rmdir命令來刪除文件,不過當遇到目錄非空,就會麻煩,下面閱讀本文學習下linux刪除文件夾和文件的命令吧
    2018-02-02
  • Linux下實現(xiàn)免密碼登錄(超詳細)

    Linux下實現(xiàn)免密碼登錄(超詳細)

    這篇文章主要介紹了Linux下實現(xiàn)免密碼登錄的相關資料,非常不錯,具有參考借鑒價值,感興趣的朋友一起看看吧
    2016-10-10
  • tr命令在統(tǒng)計英文單詞出現(xiàn)頻率中的妙用

    tr命令在統(tǒng)計英文單詞出現(xiàn)頻率中的妙用

    今天小編就為大家分享一篇關于tr命令在統(tǒng)計英文單詞出現(xiàn)頻率中的妙用,小編覺得內容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-03-03
  • centos源碼編譯php5 mcrypt模塊步驟詳解

    centos源碼編譯php5 mcrypt模塊步驟詳解

    服務器安裝的是php5.3版本,源中沒有包含mcrypt擴展,只有自己從源碼中編譯mcrypt模塊了,看下面的詳細步驟
    2013-12-12
  • Ubuntu Server 14.04升級Ubuntu Server 16.04

    Ubuntu Server 14.04升級Ubuntu Server 16.04

    這篇文章主要介紹了 Ubuntu Server 14.04升級Ubuntu Server 16.04,具有一定的參考價值,感興趣的小伙伴們可以參考一下。
    2016-12-12
  • Linux運維基礎進程管理及環(huán)境組成分析

    Linux運維基礎進程管理及環(huán)境組成分析

    這篇文章主要為大家介紹了Linux運維基礎,對其中進程管理及環(huán)境組成分析作了詳細的分析,有需要的朋友可以借鑒參考下,希望可以有所幫助
    2021-09-09
  • 在 Linux 中不使用 CD 命令進入目錄/文件夾的方法

    在 Linux 中不使用 CD 命令進入目錄/文件夾的方法

    眾所周知,如果沒有 cd 命令,我們無法 Linux 中切換目錄。接下來通過本文給大家介紹了在 Linux 中不使用 CD 命令進入目錄/文件夾的方法,需要的朋友可以參考下
    2019-04-04
  • CentOS?6?Linux系統(tǒng)添加永久靜態(tài)路由的方法

    CentOS?6?Linux系統(tǒng)添加永久靜態(tài)路由的方法

    在Linux系統(tǒng)中,特別是對于服務器管理而言,正確配置網絡路由是確保網絡通信順暢的重要步驟,本文將介紹如何在CentOS?6系統(tǒng)中添加永久靜態(tài)路由,通過本文的學習,你將能夠掌握如何在不影響現(xiàn)有網絡配置的情況下,為你的系統(tǒng)添加一條或多條靜態(tài)路由,需要的朋友可以參考下
    2025-03-03
  • linux下快速列出局域網中所有主機名(計算機名)的腳本

    linux下快速列出局域網中所有主機名(計算機名)的腳本

    這篇文章主要介紹了linux下快速列出局域網中所有主機名(計算機名)的腳本,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-07-07
  • linux vi命令知識點用法總結

    linux vi命令知識點用法總結

    在本篇文章里小編給大家整理的是關于linux vi命令的相關知識點內容,有需要的朋友們參考學習下。
    2019-10-10

最新評論