Linux進程——進程地址空間

前言:在講完環境變量后,相信大家對Linux有更進一步的認識,而Linux進程概念到這也快接近尾聲了,現在我們了解Linux進程中的地址空間!


在這里插入圖片描述


本篇主要內容:
了解程序地址空間
理解進程地址空間
探究頁表和虛擬地址空間

在這里插入圖片描述


進程地址空間

  • 1. 程序地址空間
  • 2. 進程地址空間
  • 3. 什么是地址空間
  • 3. 地址空間的管理
  • 4. 頁表
  • 5. 為什么要存在地址空間
  • 6. 總結拓展


1. 程序地址空間

我們在學習C語言的時候,大家都了解過這樣的空間布局圖

在這里插入圖片描述
那么到底是不是這樣排布的呢,我們來驗證一下

    1 #include<stdio.h>2 #include<stdlib.h>3 4 int un_gval;5 int init_gval = 100;                         6                                      7 int main(int argc, char *argv[], char *env[])8  {                                            9      printf("code addr: %p\n", main);                   10      const char *str = "Hello, Linux!";                 11      printf("read only char addr: %p\n", str);          12      printf("init global value addr: %p\n", &init_gval);13      printf("uninit global value addr: %p\n", &un_gval);14                                     15      char *heap1=(char*)malloc(100);16      char *heap2=(char*)malloc(100);17      char *heap3=(char*)malloc(100);18      char *heap4=(char*)malloc(100);19                                        20      int a = 100;                      21                                        22      printf("heap1 addr: %p\n", heap1);23      printf("heap2 addr: %p\n", heap2);24      printf("heap3 addr: %p\n", heap3);25      printf("heap4 addr: %p\n", heap4); 26                                         27      printf("stack addr: %p\n", &str);  28      printf("stack addr: %p\n", &heap1);                                                                                                                                                       29       printf("stack addr: %p\n", &heap2);                                                                                                                                                30       printf("stack addr: %p\n", &heap3);31      printf("stack addr: %p\n", &heap4);                                                                                                                                                                  32      printf("a addr: %p\n",&a);  33      return 0;34  }

在這里插入圖片描述


棧區中的數組和結構體

int num[10] ......&a[0]  &a[9]struct s
{int a; ......&s.aint b; ......&s.bint c; ......&s.c
}

在這里插入圖片描述

注意:棧區是整體向下增長,局部想上使用的,就是地址最低處,依次往上放后面的元素


但是如果我們將代碼更改還能運行過去嘛?

char *str = "Hello, Linux!"; 
*str = 'S';

在這里插入圖片描述
顯然我們是不能更改的,一更改就就運行不了了

注意:其實是因為字符常量區與代碼區很接近,而編譯器在編譯時,字符常量區就是被編譯到代碼區的,代碼又不可被寫入,所以字符常量區也不可被修改

綜上:

  • 棧區是整體向下增長,局部想上使用的,就是地址最低處,依次往上放后面的元素
  • 常量區的字符串不允許修改

但是這都是我們之前了解的知識,現在我們來重新了解地址,我們先來看這段代碼

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

在這里插入圖片描述
我們發現在開始時,輸出出來的變量值和地址是一模一樣的!
因為我們之前講過子進程按照父進程為模版,父子并沒有對變量進行進行任何修改

但是在達到一定條件之后,父子進程,輸出地址是一致的,但是變量內容不一樣!

但是相同的地址為什么會有不同的值?

  • 所以我們能得出結論,我們之前看到的地址,絕對不是物理地址,我們平時用到的地址,其實都是虛擬地址/線性地址!
  • 而虛擬地址就是進程地址空間的內容

2. 進程地址空間

我們現在來深入的了解一下為什么相同的的地址為什么會有不同的值?

首先引入一個概念:每一個進程運行之后,都會有一個進程地址空間的存在,在系統層面都要有自己的頁表映射結構!
在這里插入圖片描述

因此:當一個進程先修改后,它就不再指向原來那塊物理空間,而是擁有一個新的物理空間!而頁表左邊的虛擬空間沒有發生改變,所以相同的的地址為什么會有不同的值,是因為映射的物理空間不同!


3. 什么是地址空間

在講什么是地址空間之前,我們先來講一個故事,來方便理解!

一個擁有10億美元身家的富豪,他有4個私生子,每個人都不知道彼此的存在,但是富豪對每個孩子都說,認真做好現在的事,在未來可以繼承自己的10個億家產。

在這里插入圖片描述

但是在得到10個億之前,他的幾個孩子,在經濟上遇到了問題,前三個都要找富豪要10w美金來解決麻煩,富豪覺得合情合理也就給了,但是它的第四個孩子直接找他要10個億,富豪當然不能給他,然后講明原因后給了他20w美金。因此他的所有孩子都可以得到10億之內的經濟資助,但是絕對拿不到10個億。

在這里插入圖片描述

在這個故事中:

  • 操作系統:富豪
  • 內存:10億美金
  • 進程:私生子
  • 虛擬地址空間:繼承10億的大餅

虛擬地址空間并不是真實的地址


3. 地址空間的管理

富豪給每一個私生子都畫了餅,他要把每個私生子都管理起來,也就是要把所有大餅管理起來。

因此:地址空間也要被OS管理起來!!每一個進程都要有地址空間,系統中,一定要對地址空間做管理!!

而操作系統管理地址空間,一定是“先描述,在組織”!地址空間最終一定是一個內核的數據結構對象,
就是一個內核結構體!

在這里插入圖片描述
而我們觀察進程地址空間,發現里面是一堆的地址劃分。
在Linux中,這個描述虛擬地址空間的東西叫做:

struct mm _struct
{long code_start;long code_end;long data_start;long data_end;long heap_start;long heap end; //brklong stack _start;long stack _end;......
}

在這里插入圖片描述
而該結構體的大小會被初始化成4gb,線性編程范圍從全0到全F,然后把線性范圍拆分成細小的范圍,這就是地址空間


4. 頁表

在上面我們了解到了頁表,頁表的映射關系中左側表示虛擬地址,右側表示物理地址,但是除了這兩個其實在頁表的映射關系中還存在一個標記字段——訪問權限字段

在這里插入圖片描述
講到這里我們再回到字符常量區那里。

char *str = "Hello, Linux!"; 
*str = 'S';

此時我們就可以解釋通字符常量區為什么不能修改:

  • 字符常量區在經過頁表映射時,訪問權限字段只設置成只讀的,所以在寫入時,頁表直接將我們攔住,不讓我們訪問,所以字符常量區不能修改,代碼區也是如此!

所以頁表可以進行安全評估,有效的進行進程訪問內存的安全檢查


在除去上面提到的東西以外,頁表還可以通過二進制衡量能存中有沒有內容,是否分配地址

在這里插入圖片描述
當我們有個虛擬地址要被訪問了,但是它并沒有被分配空間,更不會有內容,那該則么辦呢?
在這里插入圖片描述

其實在這個時候操作系統會將你的這個訪問暫停,然后進行一下操作:

  • 操作系統會將你的可執行程序重新開辟空間
  • 把對應可執行程序需要執行的這個虛擬地址對應的代碼加載到內存里
  • 把對應的虛擬地址填充到頁表
  • 把標志位改為1,代表已經分配地址,且內容已經填充
  • 將暫停的代碼繼續訪問

操作過程也稱為缺頁中斷

而我們操作系統在進行這些工作時,是在進行內存管理, 而進程管理和內存管理因為有了地址空間的存在 ,實現了在操作系統層面上的模塊的解耦!


5. 為什么要存在地址空間

到了這里我想大家也都了解得差不多了,為什么要存在地址空間,原因有很多

一、 讓無序便有序

  • 讓進程以統一的視角看待內存
  • 在頁表層映射時會將不同的數據類型進行劃分使得映射到物理內存后是比較有序的一種狀態!
  • 所以任意一個進程,可以通過地址空間+頁表可以將亂序的內存數據,變成有序,分門別類的規劃好!

二、存在虛擬地址空間,可以有效的進行進程訪問內存的安全檢查

三、將進程管理和內存管理進行解耦

四、保證進程的獨立性

通過頁表讓進程雖然虛擬地址一樣但是映射到不同的物理內存處,從而實現進程的獨立性

6. 總結拓展

拓展:
在mm_struct中還會存在一個struct vm_area_struct的結構 ,它能劃分出一個start,一個end。如果我們還想繼續劃分就會有多個struct vm_area_struct的結構,然后他們會構成一個線性劃分的鏈表結構。

struct vm_area_struct
{struct mm_struct * vm_mm;unsigned long vm_start;unsigned long vm_end;......
}

到這里我們的進程地址空間也接近尾聲了,地址空間讓進程管理和內存管理互不干涉,起到了很大作用。結束進程地址空間,我們的Linux進程概念到這里也結束了,后面我將帶大家走進進程控制。

謝謝大家支持本篇到這里就結束了

在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/12786.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/12786.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/12786.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

matlab使用教程(71)—控制坐標區布局

1.與位置相關的屬性和函數 有幾個屬性和函數可用于獲取和設置坐標區的大小與位置。下表摘要顯示了這些屬性和函數。 函數或屬性描述 OuterPosition 屬性 使用此屬性可以查詢或更改坐標區的外邊界&#xff0c;包括標題、標簽和邊距。要更改外邊界&#xff0c;請將此屬性指定為…

MySQL、JDBC復盤及規劃

數據庫仍有習題尚未做完&#xff0c;策略從一天做完改為每天5到10題&#xff0c;以此達到掌握和復習的效果&#xff0c;JDBC的六部仍需每天練習&#xff0c;從明天開始正式進行JavaWeb的學習&#xff0c;預計持續到七月中旬&#xff0c;還會完成一個書城項目&#xff0c;六月底…

基于Hadoop的課程診改大數據可視化分析研究與應用

基于Hadoop的課程診改大數據可視化分析研究與應用 “A Study and Application of Big Data Visualization Analysis for Course Diagnosis and Improvement based on Hadoop” 完整下載鏈接:基于Hadoop的課程診改大數據可視化分析研究與應用 文章目錄 基于Hadoop的課程診改大…

Vue 快速入門:Vue初級

語法規則 前端渲染 渲染有幾種方式&#xff1a;原生js、js模板、Vue模板語法 原生js 使用字符串拼接 js模板語法 Vue.js 模板語法概述 Vue.js 是一個用于構建用戶界面的漸進式框架&#xff0c;其模板語法非常靈活和直觀。Vue 的模板語法基于 HTML&#xff0c;可以通過指令…

Symbol類型的作用

在TypeScript&#xff08;和JavaScript&#xff09;中&#xff0c;Symbol 是一個內置對象&#xff0c;它提供了一個唯一的且不可改變的數據類型&#xff0c;用于作為對象的鍵&#xff08;key&#xff09;。這種類型主要用于避免命名沖突&#xff0c;特別是在使用像 for...in 或…

kali更換鏡像源

vim /etc/apt/sources.list.d/docker.list 或 vim /ect/apt/sources.list #清華大學源 deb http://mirrors.tuna.tsinghua.edu.cn/kali kali-rolling main contrib non-free deb-src https://mirrors.tuna.tsinghua.edu.cn/kali kali-rolling main contrib non-free #中科大 de…

PID調節常見的問題----積分飽和等問題--參考學習

1&#xff0c; PID控制學習筆記之三—積分的處理 https://zhuanlan.zhihu.com/p/264238608 2&#xff0c;PID控制參數整定&#xff08;調節方法&#xff09;原理圖示MATLAB調試 https://blog.csdn.net/viafcccy/article/details/107988093 3&#xff0c;如何理解PID控制算法中…

Java為什么會成為現在主流的編程語言

Java為什么會成為現在的主流語言 前言一、Java語言概述Java是什么為什么大多數人會選擇從事Java為什么從事Java的工作者數量從年遞減 二、Java語言的特點簡單性面向對象分布式&#xff08;微服務&#xff09;健壯性安全性體系結構中立可移植性解釋型高性能多線程動態性 三、Jav…

UDP多對多組播通信

廣播和多播僅應用于UDP。TCP是一個面向連接的協議&#xff0c;TCP一定是點對點的&#xff0c;一點是兩個主機來建立連接的&#xff0c;TCP肯定是單播。只有UDP才會使用廣播和組播。 如下示例實現一個UDP多對多的組播通信&#xff0c;進程中有收、發兩個線程&#xff0c;分別表…

6款電腦精選工具軟件推薦!

AI視頻生成&#xff1a;小說文案智能分鏡智能識別角色和場景批量Ai繪圖自動配音添加音樂一鍵合成視頻https://aitools.jurilu.com/ 1.IP地址查看工具——純真ip數據庫 純真IP數據庫是一個易于操作的IP地址查詢工具&#xff0c;它允許用戶通過輸入IP地址來查詢其對應的地理位置…

Django創建網站的地基

相關文檔 1、為新網站創建一個文件夾&#xff08;這里是&#xff1a;locallibrary&#xff09; D:\django>mkdir locallibraryD:\django>cd locallibraryD:\django\locallibrary>dirVolume in drive D is 新加卷Volume Serial Number is B68C-03F7Directory of D:\dj…

【Uniapp】簡易封裝提示框showToast/showModal

組件 // 封裝提示框 export const showModal (content, showCancel false, title "提示") > {return new Promise((resolve, reject) > {uni.showModal({title: title,content: content,showCancel: showCancel,success: (res) > {resolve(res);},fail:…

Linux計劃任務功能介紹

一次性計劃任務(不能跨越0點) at 16:20 at> echo hello | wall at> at 1621 at> mkdir /tmp/date %F at> at 16:2212022015 at> rm -fr /tmp/* at> job 33 at 2015-12-02 16:22 atq 查詢計劃任務 atrm 刪除計劃任務 atrm 33 /etc/at.deny 拒絕使用at …

結合多模態 AI 谷歌展示 AR 眼鏡原型機;Meta 被曝開發帶攝像頭的 AI 耳機丨 RTE 開發者日報 Vol.204

開發者朋友們大家好&#xff1a; 這里是 「RTE 開發者日報」&#xff0c;每天和大家一起看新聞、聊八卦。我們的社區編輯團隊會整理分享 RTE&#xff08;Real Time Engagement&#xff09; 領域內「有話題的新聞」、「有態度的觀點」、「有意思的數據」、「有思考的文章」、「…

如何修改android 項目顯示的app名

修改vlaues下的string.xml文件 修改這個標簽中的內容就行

國產銀河麒麟V10SP1系統安裝Qt和MySql步驟

安裝軟件&#xff1a;準備好Kylin-Desktop-V10-SP1-Release-hwe-2107-x86_64.iso和qt-opensource-linux-x64-5.14.2.run 安裝步驟&#xff1a; 1、VMWare軟件中新建一個虛擬機并安裝Kylin-Desktop-V10-SP1-Release操作系統&#xff0c;安裝時候輸入密碼的地方記得要用英文&am…

“網絡安全新紀元:等保2.0的詳細解讀與實踐”

網絡安全等級保護基本要求》&#xff08;等保2.0&#xff09;于2019年6月發布&#xff0c;是我國網絡安全等級保護制度的一項重要標準。等保2.0主要針對關鍵信息基礎設施的網絡安全保護&#xff0c;對數據安全和個人信息保護提出了更高的要求。本文將對等保2.0進行詳細解讀&…

3.深度學習課程--技術棧

上一節我們概覽了深度學習的主要內容及其應用領域&#xff0c;解決了學習的初衷和用途問題。在深入算法和模型之前&#xff0c;本小節將介紹課程所需的技術棧和準備事項。雖然這些準備看似簡單&#xff0c;但它們對于后續學習至關重要。 首先&#xff0c;我們將使用Python作為…

動態路由實驗新手入門:快速掌握核心知識點

大家好&#xff0c;這里是G-LAB IT實驗室。今天帶大家學習一下華為動態路由實驗配置&#xff0c;新手入門&#xff0c;快速掌握核心知識點&#xff01; 01、實驗拓撲 02、實驗需求 1.根據拓撲運行對應的路由協議 2.每個路由器都有自己的環回口&#xff0c;宣告的區域不限制 …

Java各大GPS坐標系互轉算法(保證好用)

不好用來捶我&#xff0c;好用的話點個贊鼓勵一下~ /*** 坐標轉換器*/ public class CoordinateConverter {private static final double x_PI 3.14159265358979324 * 3000.0 / 180.0;private static final double PI 3.1415926535897932384626;private static final double…