精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

Linux程序地址空間詳解

dyquk4xk2p3d ? 來源:入門小站 ? 2023-03-26 10:39 ? 次閱讀

1 代碼感受

在正式講程序[地址空間]前我們先來看一段簡單的代碼來分析分析:

1#include
2#include
3usingnamespacestd;
4
5intg_val=100;
6
7intmain()
8{
9pid_tid=fork();
10if(id==0)
11{
12//child
13while(true)
14{
15cout<<"我是一個子進程,我的pid是:"<

大家可以自己先分析一下結果。

我們來運行一下結果:

01d0501a-ca69-11ed-bfe3-dac502259ad0.png

大家看前面幾行可能就會立馬發現問題:我們定義的 g_val 是全局變量,當子進程修改 g_val 的值時我們發現父進程的 g_val 是不受影響的,那么說明父子進程所用的 g_val 并不是同一個變量(這個很好理解,之前的我們說過父子進程是相互獨立的,互相不受干擾的),但是問題出現在最后一列,我們驚奇的發現居然父子進程的 g_val 變量的地址居然是相同的,前面不是說父子進程的 g_val 不是同一個變量嗎?這里為啥打印出來的地址會是相同的呢?

這里就說明我們打印出來的地址并不是真正的[物理地址],我們語言層面打印出的地址叫做虛擬地址或者線性地址。我們在用C/C++語言所看到的地址,全部都是虛擬地址!而物理地址,用戶一概看不到,由OS統一管理 。OS必須負責將虛擬地址轉化成物理地址。

2 進程地址空間

首先我們來講一個故事:從前有一個企業家很有錢,他的家產大概有一億美金左右的樣子。他有 4 個私生子,并且這四個私生子互相并不知道對方的存在。第一個私生子是個學霸,在國內頂尖學校上學,這個富豪便對他說,你要好好讀書,將來我這一億美金全部都是你的;第二個私生子是一個三線演員,富豪便對他說,我幫你打開你紅的渠道,你不要辜負了我對你的期望,好好努力,將來我這一億美金都是你的;第 3 個私生子是個女兒,當的是小學老師,富豪便對他說,你也不用太過努力工作,我就你這一個女兒,等我老了這一億美金就是你的了;第四個私生子是一個初中的小混混,富豪對他說,你只要好好聽我的話,這一億美金就是你的了。

富豪給每個私生子都做出了承諾要將一億美金給他們,但是實際富豪并沒有那么多的錢給每個私生子一億美金,而這一億美金就是富豪給私生子們畫的一張大餅,但是它的私生子們卻信以為真。

那這個故事與我們講的知識有什么關系呢?其實操作系統就是那個富豪,私生子們就是一個一個的進程,而那一億美金就是進程地址空間。

PS: 我們在生活中要盡量少畫餅。

操作系統給進程畫了一張大餅,操作系統的資源是有限的,所以他就得要好好的把這張餅給管理起來,不讓這些進程亂來,而如何管理呢?

那就要先描述,再組織,Linux 中用的是一種叫做 mm_struct 的內核數據結構來管理的。

我們來用一張圖帶大家來看看程序地址空間:

02f7097a-ca69-11ed-bfe3-dac502259ad0.png

這張圖相信大家多多少少也不會陌生,在 C 語言的學習中我們也見到了很多次。

那么程序地址空間如何編碼的呢?(32 位的平臺下[虛擬地址]空間大概是 4GB)

ps: 下面圖每個小空格代表著一個字節。

03145214-ca69-11ed-bfe3-dac502259ad0.png

所以從這里我們也不難看出為啥虛擬地址也叫做線性地址。那么我們究竟是如何管理虛擬地址空間的每個區的呢?

我們可以用下面這種方式來描述管理:

structmm_struct
{
longcode_start;
longcode_end;
longinit_start;
longinit_end;
…………
longbrk_start;
longbrk_end;
longstack_start;
longstack_end;
}

而_start 和_end 限定的區域就是叫做虛擬地址(線性地址)

那么問題來了,既然上面我們講了那么多虛擬地址,真正的物理地址又在哪里呢?

我們畫一個圖方便大家理解:

035326ba-ca69-11ed-bfe3-dac502259ad0.png

通過這張圖大家并不難發現,我們在語言層面上的地址是地址空間的虛擬地址,而虛擬地址要與物理地址建立映射,就需要一張頁表(頁表的工作原理我們將放到后面來講)。

我們在學習 C 語言時大家在書上看到這樣的一句代碼:const char* str="hello world";

這時書上會告訴大家這句 str 指向的內容是只讀的,不可修改的,但是這時為什么呢?這時我們就可以自己來分析分析:str 指向的內容是在常量字符區,當常量字符區通過頁表與物理地址建立映射時在頁表中就將該數據設置為只讀,當我們后續有修改操作時就會直接報錯。

有了上面的基礎我們就可以來解釋解釋為啥開頭我們的 g_val 是同一個地址,但是指向的內容卻不相同的問題了:

037def76-ca69-11ed-bfe3-dac502259ad0.png

當不修改數據時就不會發生寫時拷貝,父子進程指向的是同一塊物理空間 (為了節約資源);當要修改數據時就會發生寫時拷貝,父子進程指向的是不同的物理空間,但是虛擬地址空間是相等的。

我們再來回答為啥 fork 會有兩個返回值的問題就很容易了,就是因為父子進程的返回值是不同的,所以肯定會發生寫時拷貝將不同的返回值用相同的虛擬地址來進行返回,雖然虛擬地址是相同的,但是他們通過頁表建立映射的關系卻是不一樣的。

到目前為止,程序地址空間的基本內容已經 ok, 接下來給出一些擴展。

3 擴展

首先引出一個問題:假如沒有程序地址空間,OS 是如何工作的?

我們知道如果沒有了地址空間,那么 cpu 將直接跟物理地址打交道,這樣做的后果是什么?

我們不難知道假如 cpu 直接跟物理地址打交道的話那么當我們從 cpu 中讀到非法地址時那就壞了,通過非法地址將我們程序中其他變量的值給修改了那不就扯淡了嗎。所以我們要通過一層屏障來保護數據,而這一層保護就是通過程序地址空間來進行的,當我們訪問的數據非法時通過頁表的映射就會拒絕你的非法操作。

所以我們得出了程序地址空間的第一個好處:防止地址隨意訪問,保護物理內存和其他進程。

在向大家提出一個小問題:當我們在堆上 new 空間時 OS 是立馬就把空間給你,還是等你需要的時候再給你?

這個問題大家應該都能夠答對,與我們想得一樣,OS 會在我們需要該空間的時候再去在堆上申請。

03db0d0a-ca69-11ed-bfe3-dac502259ad0.png

而頁表暫時沒有與物理內存建立映射關系稱作頁表中斷,當我們需要空間的時候再與 · 物理內存建立映射。大家從這張圖看出來沒有,當我們通過頁表建立映射時將進程管理與內存管理給解耦合了。我進程管理不需要關心你是怎樣在內存上申請空間的,內存管理也不需要關心進程是如何管理起來的,這樣下來維護成本就會變得更低,維護效率會更加高效一些。

所以我們得出了程序地址空間的第二個好處:將進程管理與內存管理進行解耦合。

再提出一個問題:程序在被編譯的時候沒有被加載到內存,那么程序內有沒有地址呢?

答案是有的。源代碼再被編譯的時候就是按照虛擬地址空間的方式將對應的代碼和數據進行編制,編譯器也會遵守虛擬地址的規則。

當我們把程序加載到內存,程序里保存的地址(虛擬地址,并不是程序本身在內存中的物理地址) 就會被 cpu 讀取, cpu 通過虛擬地址找到對應的虛擬地址空間,然后虛擬地址空間又通過頁表映射到物理內存中,這樣就將程序的整個運轉給聯系起來了。

所以我們得出了程序地址空間的第三個好處:可以讓進程以統一的視角看待自己的代碼和數據。

最近很多小伙伴找我要一些程序員必備資料,于是我翻出了壓箱底的寶藏,免費分享給大家!

審核編輯:湯梓紅

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 內核
    +關注

    關注

    3

    文章

    1363

    瀏覽量

    40228
  • Linux
    +關注

    關注

    87

    文章

    11230

    瀏覽量

    208931
  • 操作系統
    +關注

    關注

    37

    文章

    6740

    瀏覽量

    123192
  • 程序
    +關注

    關注

    116

    文章

    3777

    瀏覽量

    80853
  • 代碼
    +關注

    關注

    30

    文章

    4750

    瀏覽量

    68357

原文標題:Linux:程序地址空間--原來操作系統也喜歡畫大餅

文章出處:【微信號:良許Linux,微信公眾號:良許Linux】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    Linux內核地址映射模型與Linux內核高端內存詳解

    Linux 操作系統和驅動程序運行在內核空間,應用程序運行在用戶空間,兩者不能簡單地使用指針傳遞數據,因為
    發表于 05-08 10:33 ?3442次閱讀
    <b class='flag-5'>Linux</b>內核<b class='flag-5'>地址</b>映射模型與<b class='flag-5'>Linux</b>內核高端內存<b class='flag-5'>詳解</b>

    Linux設備驅動開發詳解

    #《Linux設備驅動開發詳解》電子書連載#第8章 Linux設備驅動中的阻塞與非阻塞IO,阻塞和非阻塞I/O是設備訪問的兩種不同模式,驅動程序可以靈活地支持用戶
    發表于 06-25 15:14

    基于嵌入式Linux應用程序開發詳解

    基于嵌入式Linux應用程序開發詳解
    發表于 10-25 14:17 ?12次下載
    基于嵌入式<b class='flag-5'>Linux</b>應用<b class='flag-5'>程序</b>開發<b class='flag-5'>詳解</b>

    基于嵌入式Linux的LCD驅動程序設計

    Linux有內核空間和用戶空間,平時工作在保護模式,每個應用程序進程都有自己的虛擬地址空間,應用
    發表于 07-27 07:31 ?1598次閱讀
    基于嵌入式<b class='flag-5'>Linux</b>的LCD驅動<b class='flag-5'>程序</b>設計

    如何為Linux編寫用戶空間設備驅動程序

    了解如何為Linux編寫用戶空間設備驅動程序。 用戶空間驅動程序為某些設備提供內核空間驅動
    的頭像 發表于 11-22 07:04 ?3713次閱讀

    高端內存的詳解linux用戶空間與內核空間

    Linux 操作系統和驅動程序運行在內核空間,應用程序運行在用戶空間,兩者不能簡單地使用指針傳遞數據,因為
    發表于 04-28 17:33 ?978次閱讀
    高端內存的<b class='flag-5'>詳解</b>:<b class='flag-5'>linux</b>用戶<b class='flag-5'>空間</b>與內核<b class='flag-5'>空間</b>

    Linux用戶空間與內核空間

    應用程序運行在用戶空間,而Linux 驅動屬于內核的一部分,因此驅動運行于內核空間。當我們在用戶空間想要實現對內核的操作,比如使用open
    發表于 05-20 10:58 ?1017次閱讀
    <b class='flag-5'>Linux</b>用戶<b class='flag-5'>空間</b>與內核<b class='flag-5'>空間</b>

    深入淺出Linux的進程地址空間

    我們知道,在32位機器上linux操作系統中的進程的地址空間大小是4G,其中0-3G是用戶空間,3G-4G是內核空間。其實,這個4G的
    的頭像 發表于 06-20 09:57 ?1925次閱讀

    Linux操作系統知識講解:走進linux 內存地址空間

    Linux操作系統知識講解:走進linux 內存地址空間
    的頭像 發表于 08-28 10:45 ?5009次閱讀
    <b class='flag-5'>Linux</b>操作系統知識講解:走進<b class='flag-5'>linux</b> 內存<b class='flag-5'>地址</b><b class='flag-5'>空間</b>

    PCI總線地址空間與系統地址空間的關系

    1、PCI地址空間 PCI總線具有32位數據/地址復用總線,所以其存儲地址空間為2的32次方=4GB。也就是PCI上的所有設備共同映射到這4
    的頭像 發表于 01-06 08:30 ?2262次閱讀

    為什么進程地址空間中要包括操作系統(內核)呢?

    這張圖就是Linux程序運行起來后所謂的進程地址空間,這里包括我們熟悉的代碼區、數據區、以及堆區和棧區。
    的頭像 發表于 04-18 09:09 ?1035次閱讀

    Linux操作系統中程序地址空間詳解

    在正式講程序[地址空間]前我們先來看一段簡單的代碼來分析分析。
    發表于 09-12 10:56 ?386次閱讀
    <b class='flag-5'>Linux</b>操作系統中<b class='flag-5'>程序</b><b class='flag-5'>地址</b><b class='flag-5'>空間</b><b class='flag-5'>詳解</b>

    Linux系統為什么需要引入虛擬地址

    Linux 系統中,采用了虛擬內存管理技術,事實上大多數現在操作系統都是如此!在 Linux 系統中,每一個進程都在自己獨立的地址空間中運行,在32 位系統中,每個進程的邏輯
    的頭像 發表于 10-07 17:28 ?903次閱讀
    <b class='flag-5'>Linux</b>系統為什么需要引入虛擬<b class='flag-5'>地址</b>

    Linux虛擬地址空間和物理地址空間的關系

    過程,這其實也是MMU的工作原理。 我們知道,在Linux中,每個進程都有自己獨立的地址空間,且互不干擾。每個進程的地址空間又分為用戶
    的頭像 發表于 10-08 11:40 ?1127次閱讀
    <b class='flag-5'>Linux</b>虛擬<b class='flag-5'>地址</b><b class='flag-5'>空間</b>和物理<b class='flag-5'>地址</b><b class='flag-5'>空間</b>的關系

    linux驅動程序運行在什么空間

    Linux 驅動程序是操作系統的一部分,負責管理硬件設備與操作系統之間的交互。驅動程序運行在內核空間(Kernel Space),這是操作系統的核心部分,與用戶
    的頭像 發表于 08-30 14:37 ?303次閱讀