【Linux】深入理解程序地址空間

🌟🌟作者主頁:ephemerals__

🌟🌟所屬專欄:Linux

目錄

前言

一、什么是程序地址空間

二、深入理解程序地址空間

1. 引例

2. 理解地址轉化

3. 再談程序地址空間

4. 補充知識

總結


前言

????????在現代操作系統中,進程的地址空間管理是實現多任務和內存保護的核心機制。對于Linux操作系統而言,理解程序的地址空間布局不僅對于開發高效、穩定的應用至關重要,也是調試和優化程序不可或缺的基礎。本文將簡要介紹Linux程序在內存中的地址空間結構,幫助讀者更好地理解進程如何利用和管理內存資源。

一、什么是程序地址空間

????????程序地址空間是指操作系統為一個程序分配的內存范圍。在現代操作系統中,每個程序在運行時都有自己的程序地址空間

程序地址空間通常分為以下幾個部分:

1. 內核空間:供操作系統使用,與其他部分形成隔離,程序無法訪問。

2. 棧區:存儲函數的局部變量和函數調用的上下文等。

3. 內存映射段(共享區):為支持文件的高效訪問或多進程的數據共享而劃分的一塊區域,通常包含文件映射、動態庫和匿名映射等。

4. 堆區:動態內存分配所用區域,需要手動管理。

5. BSS段:存儲未初始化的全局變量和靜態變量。

6. 數據段(靜態區):存儲已經初始化的全局變量和靜態變量。

7. 代碼段(常量區):存放程序的可執行代碼和只讀常量,該區域通常只讀,不可修改

在32位系統下,程序地址空間一共有2^32個地址,大小為4GB;

在64位系統下,程序地址空間一共有2^64個地址,大小約為17179PB(是理論極限,實際比它小得多,并且整個內存大小遠遠達不到如此)?。

二、深入理解程序地址空間

1. 引例

? ? ? ? ?首先我們寫一段程序:

#include <stdio.h>
#include <unistd.h>int main()
{int m = 0;pid_t id = fork();if(id == 0) // 子進程{m = 10;printf("子進程修改了m\n");sleep(1);printf("子進程:m = %d;&m = %p\n", m, &m);}else // 父進程{sleep(1);printf("父進程:m = %d;&m = %p\n", m, &m);}return 0;
}

這里我們使用fork創建了一個子進程,并讓子進程修改m的值,此時會發生寫時拷貝,兩個進程的“m”應該不再表示同一份資源。接下來打印它們的值和地址。程序運行結果如下:

可以看到,出現了怪事:m的值不同,為什么它們的地址還相同呢?

只能說明:這個地址是假的,不是真實的內存地址(物理地址)。?

實際上,我們使用C/C++編程時使用到的地址,全部都是虛擬地址,并不表示真實的內存地址。為了保護物理內存,真實的內存地址是由操作系統統一管理的,用戶無法直接訪問。

2. 理解地址轉化

? ? ? ? 因此,剛才的例子當中,兩個m的虛擬地址是相同的,但在物理層面,它們的物理地址是不同的。這就意味著兩個進程的虛擬地址空間是不同的,并且操作系統必須將用戶使用的虛擬地址轉化為物理地址,然后進行訪問等操作。負責虛擬地址和物理地址轉化的東西,叫做頁表

? ? ? ? 我們可以暫時將頁表理解為一個映射表,表的左邊是虛擬地址,右邊是物理地址,通過左邊的虛擬地址就可以進行頁表轉化,找到真實的物理地址進行訪問。

總結:

1. 一個進程具有一個程序地址空間

2. 一個進程具有一個頁表,用于虛擬地址和物理地址的轉化

3.?程序執行時,操作系統根據數據或代碼的虛擬地址,通過頁表找出對應的真實內存地址,進行訪問。

3. 再談程序地址空間

? ? ? ? 因此,再說“程序地址空間”就不太準確了,我們稱其為“進程地址空間”或“虛擬地址空間”更為恰當。

? ? ? ? 實際上,不僅進程地址空間的地址是虛擬的,其“大小”也是虛擬的。進程地址空間就像是操作系統給進程畫的一張大餅,讓進程以為自己獨占4GB的內存(32位系統下)。但由于其他進程可需要訪問物理內存,物理內存總共就4GB,怎么可能被一個進程獨占呢?所以雖說進程地址空間大小是4GB,但實際根本不可能有這么多。

? ? ? ? 因此,進程在創建時,操作系統按照程序代碼和數據的大小,創建地址空間,并設定各個區域的范圍和內存大小,然后加載程序,申請相應的物理內存,再創建頁表,支持將物理地址轉化為虛擬地址,供上層用戶使用。

? ? ? ? 這樣,我們就可以解釋剛才的程序:

1. 子進程在創建之后,拷貝了父進程的進程地址空間以及頁表,因此,父子進程的地址映射關系是相同的,具體表現就是虛擬地址相同,且維護的是同一塊物理內存。

2. 此時子進程修改變量m的值,操作系統檢測到變量要被修改,于時發生寫時拷貝,在物理內存中對該變量進行拷貝,并修改子進程的頁表映射關系,使原來的虛擬地址映射到別的物理地址處。這樣,父子進程就各自維護一個m,它們表現出的虛擬地址相同,但物理地址不同,頁表映射關系也不同,因此出現了地址相同,值不相同的情況。

那么為什么不支持直接訪問物理內存,而這樣大費周折地搞出一個什么進程地址空間和頁表呢?有三點原因:

1. 如果每個進程都可以直接訪問物理內存,那么就意味著這個程序可以直接修改另一個程序甚至操作系統的數據和代碼,如果有惡意病毒程序,就會造成不可預料的后果。

2. 假設進程A需要申請地址為1~100的內存區域,并且代碼中訪問了地址為“50”的內存單元。下一次啟動進程A時,如果已經有進程申請了1~100的內存區域,那么進程A如何申請內存呢?尚且申請101~200,但是代碼中訪問“50”已經寫死了,沒法修改,這導致每次程序執行的結果都是不確定的。

3. 如果直接使用物理內存,那么一個進程就是一整塊內存區域,如果需要執行掛起或其他操作,就只能將整個區域都進行拷貝,效率降低。

進程地址空間的出現,就完美地解決了這些問題:

1. 地址轉換過程中,可以對操作的合法性進行判定(頁表中,針對虛擬地址空間中的各個區域,有明確的權限劃分,假如在程序中修改常量數據,就會出現頁表權限攔截,發生崩潰),從而保護物理內存,確保程序的正常執行。

2. 有了虛擬地址,物理內存申請就不必連續,經過頁表可以轉化成連續的虛擬地址,方便上層使用

3. 除此之外,程序地址空間還使得操作系統對進程的管理內存的管理之間進行一定的解耦合(用戶申請內存根本無需關心物理內存的具體情況)

4. 補充知識

1. 虛擬地址空間的本質是一個數據結構,在Linux下叫做mm_struct,其地址存放在task_struct對象當中,mm_struct維護著一個個vm_area_struct,這些vm_area_struct存儲著進程地址空間每一個區域的起始和結束地址。要調整區域劃分,只需對其中變量進行加減操作。

2. 一個進程具有一個進程地址空間,意味著一個進程維護一個mm_struct,操作系統要將這些mm_struct組織起來統一管理。當進程數量較少時,mm_struct是用單鏈表結構組織起來的;較多時,利用紅黑樹結構進行組織。

總結

? ? ? ? 本篇文章,我們學習了進程地址空間的基本概念,并深入理解了頁表轉化以及進程地址空間的本質。學習進程地址空間,為我們后續學習理解進程控制相關操作至關重要。如果你覺得博主講的還不錯,就請留下一個小小的贊在走哦,感謝大家的支持???

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

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

相關文章

【深度學習-Day 5】Python 快速入門:深度學習的“瑞士軍刀”實戰指南

Langchain系列文章目錄 01-玩轉LangChain&#xff1a;從模型調用到Prompt模板與輸出解析的完整指南 02-玩轉 LangChain Memory 模塊&#xff1a;四種記憶類型詳解及應用場景全覆蓋 03-全面掌握 LangChain&#xff1a;從核心鏈條構建到動態任務分配的實戰指南 04-玩轉 LangChai…

解決在 Linux 中 WPS 字體缺失問題

解決在 Linux 中 WPS 字體缺失問題 安裝方式 安裝方式 首先下載你所需要的字體文件 在字體文件所在的目錄下右鍵點擊在命令行中打開 或 Open in Terminal sudo mkdir /usr/share/fonts/myfontssudo cp ./* /usr/share/fonts/myfonts執行命令&#xff0c;更新字體緩存 sudo fc…

668SJBH報刊發行系統

1 前言 隨著我國信息產業的迅猛發展&#xff0c;手工管理方式已不適應社務管理的要求&#xff0c;報社的日常管理正面臨著信息化的挑戰&#xff0c;采用計算機管理以提高服務質量和管理水平勢在必行。發行管理是社務管理的一個重要組成部分&#xff0c;是報社和客戶聯系的紐帶…

K8S - 從零構建 Docker 鏡像與容器

一、基礎概念 1.1 鏡像&#xff08;Image&#xff09; “軟件的標準化安裝包” &#xff0c;包含代碼、環境和配置的只讀模板。 技術解析 鏡像由多個層組成&#xff0c;每層對應一個Dockerfile指令&#xff1a; 應用代碼 → 運行時環境 → 系統工具鏈 → 啟動配置核心特性…

better_fbx 下載

目錄 v6.0.5下載&#xff1a; better_fbx 下載 v6.0.5下載&#xff1a; Blender FBX模型導入導出插件 Better FBX Importer & Exporter V6.0.5V5.4.10 For Blender 2.8 | 齲齒一號GFXCamp better_fbx 下載 How To Install Launch Blender, navigate to Edit->User P…

Spring AOP 典型應用場景

AOP 典型應用場景 1. 日志記錄&#xff08;Logging&#xff09;代碼實現 2. 權限校驗&#xff08;Authentication&#xff09;代碼實現 3. 性能監控&#xff08;Performance Monitoring&#xff09;代碼實現 4. 緩存處理&#xff08;Caching&#xff09;代碼實現 5. 重試機制&a…

開始一個vue項目-day2

這次新增的功能有&#xff1a; 1、使用cookie存儲token 參考網站:https://vueuse.org/ 安裝包&#xff1a; npm i vueuse/integrations npm i universal-cookie^7 2、cookie的設置讀取和刪除&#xff0c;代碼&#xff1a;composables/auth.js import { useCookies } from …

「Mac暢玩AIGC與多模態18」開發篇14 - 多字段輸出與結構控制工作流示例

一、概述 本篇在輸入變量基礎上,演示如何通過執行 LLM 節點輸出多個結構化字段,并傳遞至結束節點。開發人員將掌握如何配置結構化輸出格式,實現提示詞與字段的準確映射,為后續引入條件判斷、循環結構等邏輯控制建立結構輸出規范基礎。 二、環境準備 macOS 系統Dify 平臺已…

JWT解析

什么是JWT JSON Web Token &#xff08;JWT&#xff09; 是一種開放標準 &#xff08;RFC 7519&#xff09;&#xff0c;它定義了一種緊湊且獨立的方式&#xff0c;用于在各方之間以 JSON 對象的形式安全地傳輸信息。此信息可以驗證和信任&#xff0c;因為它是經過數字簽名的。…

C語言中的自定義類型 —— 結構體.位段.聯合體和枚舉

自定義類型 1. 前言2. 結構體2.1 結構體的聲明2.2 結構體變量的定義和初始化2.3 結構體的特殊聲明2.4 結構體的自引用2.5 結構體的內存對齊2.6 修改默認對齊數2.7 結構體傳參 3. 位段4. 聯合體5. 枚舉6. 結言 1. 前言 在C語言中已經為用過戶提供了內置類型&#xff0c;如&…

StarRocks 查詢優化器深度解析

StarRocks 查詢優化器概覽 1. Development History of StarRocks 過去五年&#xff0c;StarRocks 發布了三個大版本&#xff1a; StarRocks 1.0&#xff1a;通過向量化引擎和 CBO&#xff0c;打造極速 OLAP 數據庫。 StarRocks 2.0&#xff1a;通過主鍵模型、數據湖分析和查詢…

如何提高情商?(優化版)

引言 提高情商&#xff08;EQ&#xff09;是一個需要長期練習和自我反思的過程&#xff0c;核心在于理解自己、管理情緒、共情他人并有效溝通。以下是一些具體且可操作的方法&#xff0c;結合理論和實際場景&#xff0c;幫助你逐步提升&#xff1a; 一、核心方法&#xff1a;…

Python爬蟲實戰:獲取好大夫在線各專業全國醫院排行榜數據并分析,為患者就醫做參考

一、引言 在當今醫療資源豐富但分布不均的背景下,患者在選擇合適的心血管內科醫院時面臨諸多困難。好大夫在線提供的醫院排行榜數據包含了醫院排名、線上服務得分、患者評價得分等重要信息,對患者選擇醫院具有重要的參考價值。本研究通過爬取該排行榜數據,并進行深入分析,…

【AI面試準備】電商購物車AI測試設計與實施

面試題&#xff1a;案例實踐&#xff1a; 為電商購物車設計AI測試&#xff1a;通過用戶行為日志訓練點擊路徑預測模型&#xff0c;動態生成邊界條件測試用例。 為了順利通過面試&#xff0c;回答應結構清晰、技術深入&#xff0c;并突出實際應用與創新。以下為分步解答&#…

Java 中使用 Callable 創建線程的方法

一、Callable 接口概述? Callable接口位于java.util.concurrent包中&#xff0c;與Runnable接口類似&#xff0c;同樣用于定義線程執行的任務&#xff0c;但它具有以下獨特特性&#xff1a;? 支持返回值&#xff1a;Callable接口聲明了一個call()方法&#xff0c;該方法會在…

2025-SMS短信驗證服務或存風險,小心賬號隱私“失守”

近期&#xff0c;火絨安全情報中心監測到一款偽裝成具備SMS短信驗證碼接收服務的程序。該程序通過部署持久化后門&#xff08;即僵尸網絡節點&#xff09;竊取敏感信息。火絨安全提醒廣大用戶務必從官方或可信渠道下載軟件&#xff0c;避免因使用來路不明的程序而導致賬號被盜或…

docker部署Open WebUI下載速度慢解決方法

docker pull ghcr.nju.edu.cn/open-webui/open-webui:main改成這個就可以了

氣泡圖、桑基圖的繪制

1、氣泡圖 使用氣泡圖分析某一年中國同歐洲各國之間的貿易情況。 氣泡圖分析的三個維度&#xff1a; ? 進口額&#xff1a;橫軸 ? 出口額&#xff1a;縱軸 ? 進出口總額&#xff1a;氣泡大小 數據來源&#xff1a;鏈接: 國家統計局數據 數據概覽&#xff08;進出口總額&…

前端面經-VUE3篇(三)--vue Router(二)導航守衛、路由元信息、路由懶加載、動態路由

一、導航守衛 vue Router 中的 導航守衛&#xff08;Navigation Guards&#xff09; 是一個非常重要的功能&#xff0c;用于在路由切換過程中&#xff0c;攔截、控制、檢查或延遲頁面跳轉。 你可以理解為&#xff1a; &#x1f510; “進門前的保安”&#xff0c;控制哪些頁面…

MATLAB實現二氧化硅和硅光纖的單模光波特性與仿真

一.二氧化硅和硅光纖的單模光波特性 利用麥克斯方程的精確解研究二氧化硅和硅亞波長直徑導線的單模光波特性。研究了單模條件、模場。 二氧化硅光纖導線是圓形截面&#xff0c;包層是空氣包層&#xff0c;階梯型變化的折射率&#xff0c;導線線徑D非常小長度足夠長&#xff0…