【Linux】地址空間

本片博客將重點回答三個問題
什么是地址空間?
地址空間是如何設計的?
為什么要有地址空間?
程序地址空間排布圖
在32位下,一個進程的地址空間,取值范圍是0x0000 0000~ 0xFFFF FFFF
在這里插入圖片描述
回答三個問題之前我們先來證明地址空間排布是按如圖所布局的
各個區空間地址驗證代碼

#include <unistd.h>
#include <stdio.h>                                                                                           
#include <stdlib.h>int g_unval; // 未初始化數據
int g_val = 100; // 初始化數據,一般指全局初始化數據
int main(int argc, char* argv[], char* env[]) // 命令行參數,環境變量
{// 代碼地址打印                          printf("code addr: %p\n", main); printf("init global addr: %p\n", &g_val);printf("uninit global addr: %p\n", &g_unval);// 堆區,指針變量本質是變量,也要開辟空間,不過放的內容是地址char *heap_mem = (char*)malloc(10);printf("heap addr: %p\n", heap_mem);// 棧區,函數內定義的變量都是在棧上開辟空間printf("stack addr: %p\n", &heap_mem); int i = 0;for (i = 0; i < argc; i++){	// 命令行參數地址	printf("argv[%d]: %p\n", i, argv[i]);}int j = 0;for (j  = 0; env[j]; j++){printf("env[%d]: %p\n", j, env[j]);}return 0;}

運行結果
在這里插入圖片描述
堆、棧之間的兩個箭頭表示
棧向地址減小的方向增長
堆向地址增大的方向增長
在這里插入圖片描述
證明方法也很簡單
在這里插入圖片描述
運行結果也證明確實是這樣
我們會發現堆區之間差了20字節
我們平時申請空間,系統會多給你一些空間
多出的空間用來記錄你堆的屬性信息
所以平時我們free空間,只要傳起始地址
剩下的系統知道要free多長的空間
在這里插入圖片描述

我們在系統部分要記的兩個口訣
1、先描述在組織
2、堆、棧相對而生

static 修飾局部變量,本質就是將該變量開辟在全局區域

所有的字面常量將來都是要映編碼進代碼的
在正文代碼上其實有一小段是字符常量區
在這里插入圖片描述

什么是地址空間以及是如何設計的

我們平時打印各種地址其實就是進程打印,程序運行之后打印的

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

有一個富豪,他有5億元家產
他有3個私生子,彼此并不知道對方存在
3個私生子分別叫張三、李四、王五
富豪為了鼓勵3個兒子
對張三說你好好念書將來5億就是你的了
對另外兩個兒子也說了同樣的話

因為不知道彼此存在
對于這三個兒子,他們都認為是5億繼承人
富豪給他們每一個兒子畫了一個大餅

有一天,張三對他爸說要1千買學習資料
李四說我成年了想買一輛兩百萬的跑車
王五說我創業需要50萬
富豪都給了他們需要的錢
只要他們要錢富豪都會給
有一天張三說要1億,富豪說要這么多干嘛
拒絕了張三,即使被拒絕了張三依舊認為自己是5億的繼承人
我們站在上帝視角知道即使富豪過世了
這三個兒子不可能都擁有5億
他們每個兒子可以斷斷續續的要錢
但永遠要不到5億,卻依然堅信自己以后能擁有這5億

對應關系
富豪 ---- 操作系統
兒子 ---- 進程
富豪畫的餅 ---- 地址空間

在內存中的地址空間本質是一種數據結構
將來要和一個特定的進程關聯起來

以前直接訪問物理內存,如果有野指針的問題
可能直接訪問到其他進程
內存本身是隨時可以被讀寫
所以在老式的程序里面野指針是會直接改了其他進程的東西
結論:直接使用物理內存不安全

現代計算機的解決方式

每個進程有自己的PCB
操作系統給每個進程一個虛擬的地址空間
通過映射機制映射到物理內存
我們可能會有疑問,最終還是會訪問物理內存
萬一虛擬地址是一個非法地址呢
其實映射機制有一個檢查機制,萬一是非法地址
可以不讓你映射

在這里插入圖片描述

虛擬地址空間究竟是什么?

每個進程都要有地址空間
就好比操作系統要給每個進程畫個餅
操作系統要給每個餅做管理
在內存中的地址空間本質是一種內核數據結構
它里面至少有各個區域的劃分
在這里插入圖片描述
我們把如圖結構稱為地址空間

區域空間并不是死的,會有一定的變化
所謂的范圍變化,本質是對start 或end 標記值 + - 特定的范圍即可
在這里插入圖片描述
所以一個地址為什么有兩個值
到這里就可以回答這個問題了

剛開始創建時只有父進程
然后創建子進程,子進程會繼承父進程的屬性
所以子進程的頁表、地址空間和父進程一樣
當子進程嘗試修改變量值時
因為要保證進程的獨立性
操作系統會重新為子進程,開辟一份物理內存
并修改子進程頁表的映射關系
但是虛擬地址并不受影響,還是一樣的地址
但映射到物理內存的不同區域
看到的值便不一樣
這種策略就叫作寫時拷貝

在這里插入圖片描述

為什么要存在地址空間

  1. 保護物理內存
    凡是非法的訪問或者映射,
    os都會識別到,并且終止你這個進程
    因為地址空間和頁表是os創建并維護的
    也就意味著凡是想使用地址空間和頁表
    進行映射,也一定要在OS的監管下進行訪問
  2. OS耦合度更低
    因為有地址空間的存在
    因為有頁表映射的存在
    我們的物理內存就可以
    對未來的數據進行任意位置的加載
    物理內存的分配就可以和
    進程的管理互不關聯
    從而使內存管理模塊和進程管理模塊
    完成解耦合

我們在C、C++語言上new、malloc空間時
本質是在虛擬地址空間申請的
因為有地址空間的存在,所以上層申請空間
物理內存可以甚至一個字節都不給你
當你真正訪問物理地址時,才執行
內存相關算法,幫你申請內存,構建
頁表映射關系,這樣空間使用率為100%
以此提高整機效率

  1. 保證進程的獨立性
    因為有地址空間的存在,每一個進程
    都認為自己擁有4GB的空間(32)
    并且各個區域是有序的,進而
    可以通過頁表映射到不同的區域
    來實現進程的獨立性,每一個進程
    不知道,也不需要知道其他進程的存在

重新理解什么是掛起?

加載的本質就是創建進程,但并不是
非得把所有程序的代碼和數據加載到
內存中,并創建內核數據結構建立映射關系
在極端情況下,只有內核結構被創建
此時就叫新建狀態

理論上,可以實現對程序的分批加載
既然可以分批加載,自然可以分批換出
一個進程短時間不會被執行,比如阻塞
而使進程的數據和代碼被換出就叫掛起

頁表不僅僅映射物理內存
磁盤位置也可以映射
所以當代碼掛起時,不用把數據
刷新到磁盤里。只要把空間直接釋放掉,
在頁表重新填上磁盤當中代碼和數據的
位置,就可以完成一次基本的掛起

擴展知識

在vim中注釋
Ctrl + v 進入視圖模式(V-BLOCK)
hjkl 選中需要注釋代碼
輸入大寫的i,左下角出現INSERT
輸入 // ,再按esc 自動注釋選中的代碼
取消注釋還是上面的操作
選中需要注釋的代碼,按d刪除

?????
本篇博客完,感謝閱讀🌹🌹🌹
如有錯誤之處可評論指出,博主會耐心聽取每條意見

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

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

相關文章

【Python數據結構與算法】—— 搜索算法 | 期末復習不掛科系列

? &#x1f308;個人主頁: Aileen_0v0&#x1f525;系列專欄: 數據結構與算法&#x1f4ab;個人格言:"沒有羅馬,那就自己創造羅馬~" 這篇博客主要探索的是計算機科學常見問題---搜索算法 “時間緊&#xff0c;任務重&#xff01;” 話不多說&#xff0c;開始今天…

HarmonyOS--ArkTS(0)--目錄

官方API文檔&#xff1a; HarmonyOS應用開發官網 - 華為HarmonyOS打造全場景新服務 華為開發者官方網站_創新從這里開始

MySQL的鎖機制

1.簡介 MySQL的隔離性是由鎖機制來保證的。鎖是計算機協調多個進程或線程并發地訪問某一資源你的機制。當多線程并發地訪問某個數據時&#xff0c;尤其是在涉及金錢等安全敏感性數據的時候&#xff0c;需要保證數據在任意時刻最多只有一個線程可以對其進行修改&#xff0c;從而…

Android 分享小結

關于作者&#xff1a;CSDN內容合伙人、技術專家&#xff0c; 從零開始做日活千萬級APP。 專注于分享各領域原創系列文章 &#xff0c;擅長java后端、移動開發、商業變現、人工智能等&#xff0c;希望大家多多支持。 目錄 一、導讀二、微信 分享 三、 QQ 、QQ空間&#xff08;Qz…

MATLAB基礎運算

矩陣和數字相乘 就是矩陣里面每個元素跟這個數字乘一遍&#xff0c;無論是點乘還是叉乘&#xff0c;對于這個都一樣。 >> Aones(3) A 1 1 11 1 11 1 1 >> 10*A ans 10 10 1010 10 1010 10 10 矩陣和矩陣叉乘 能不能相…

C++普通函數與函數模板的調用規則

調用規則 如果函數模板和普通函數都可以實現&#xff0c;優先調用普通函數可以通過空模板參數列表來強制調用函數模板函數模板也可以重載如果函數模板可以產生更好的匹配&#xff0c;優先調用函數模板 總結&#xff1a;既然提供了函數模板&#xff0c;最好就不要提供普通函數…

CSS 如何居中 DIV

如何居中 div&#xff1f; 水平居中&#xff1a;給 div 設置一個寬度&#xff0c;然后添加 margin:0 auto 屬性 div {width: 200px;margin: 0 auto; }水平居中&#xff0c;利用 text-align:center 實現 .container {background: rgba(0, 0, 0, 0.5);text-align: center;font…

基于ssm鐵嶺河醫院醫患管理系統論文

摘 要 21世紀的今天&#xff0c;隨著社會的不斷發展與進步&#xff0c;人們對于信息科學化的認識&#xff0c;已由低層次向高層次發展&#xff0c;由原來的感性認識向理性認識提高&#xff0c;管理工作的重要性已逐漸被人們所認識&#xff0c;科學化的管理&#xff0c;使信息存…

logback的使用

1 logback概述 SLF4J與其它日志組件調用關系圖如下所示。 SLF4J&#xff0c;即Java中的簡單日志門面&#xff08;Simple Logging Facade for Java&#xff09;&#xff0c;不是具體的日志解決方案&#xff0c;它只服務于各種各樣的日志系統。 SLF4J最常用的日志實現框架是&am…

2023 CCF中國軟件大會(CCF ChinaSoft) “區塊鏈可靠性分析”論壇成功召開

2023年12月1日上午&#xff0c;2023年度CCF中國軟件大會區塊鏈可靠性分析論壇成功召開。 本次論壇由中山大學鄭子彬、澳門科技大學張濤、中科院軟件所蔡彥和中山大學陳嘉弛四位老師聯合組織舉辦。本論壇重點關注區塊鏈可靠性&#xff0c;邀請了近年來在區塊鏈可靠性研究方面有先…

【postgresql】ERROR: INSERT has more expressions than target columns

執行下面sql insert into apply_account_cancellation3 select * from pply_account_cancellation; 返回下面錯誤信息 insert into apply_account_cancellation3 select * from apply_account_cancellation > ERROR: INSERT has more expressions than target colu…

【Rust】第二節:入門(如入)

1 說明 包含"Hello, world!“以及"Hello, cargo!” 環境&#xff1a;MacOS 2 Hello world 2.1 運行 1、建一個目錄 2、用vscode打開 3、新建文件main.js 4、輸入 fn main(){println!("Hello, world!"); }5、打開終端&#xff0c;執行rustc main.rs 6、…

Java:字節流 文件輸出與讀入方法 并 實現文件拷貝

文章目錄 字節 流FileOutputStream換行 與 續寫FileInputstream實現 文件拷貝&#xff08;字節數組 讀入方法&#xff09;字節流 編碼 字節 流 FileOutputStream 創建對象&#xff0c;指定位置&#xff08;產生數據傳輸通道&#xff09; 參數可以是File對象&#xff0c;也可以…

特征驅動開發

FDD 方法來自于一個大型的新加坡銀行項目。FDD 的創立者 Jeff De Luca 和 Peter Coad 分別是這個項目的項目經理和首席架構設計師。在 Jeff 和 Peter 接手項目時&#xff0c;客戶已經經歷了一次項目的失敗&#xff0c;從用戶到高層都對這個項目持懷疑的態度&#xff0c;項目組士…

mysql面試題——日志

一&#xff1a;為什么需要REDO日志 緩沖池可以幫助我們消除CPU和磁盤之間的鴻溝&#xff0c;checkpoint機制可以保證數據的最終落盤&#xff0c;然而由于checkpoint 并不是每次變更的時候就觸發 的&#xff0c;而是master線程隔一段時間去處理的。所以最壞的情況就是事務提交后…

持續集成交付CICD:Jenkins配置Nexus制品發布

目錄 一、實驗 1.Jenkins配置Nexus制品發布 一、實驗 1.Jenkins配置Nexus制品發布 &#xff08;1&#xff09;策略 發布其實就是下載制品&#xff0c;然后將制品發送到目標主機&#xff0c;最后通過腳本或者指令啟動程序。 &#xff08;2&#xff09;安裝Maven Artifact …

前端知識(十一)———js判斷上傳的文件是GBK編碼還是UTF-8

1、獲取文件二進制數據&#xff0c;這里只做示例&#xff0c;例如element-ui中文件上傳的beforeUpload方法&#xff0c;返回的file對象&#xff0c;然后使用FileReader對其進行轉換&#xff0c;再進行后續判斷 function beforeUpload(file: File) { const reader new FileRe…

uniapp圖片預覽

用的是Uview組件庫里面的 直接在頁面寫上&#xff1a; <u-album singleSize"100" :urls"[https://lxt.jingyi.icu/item.img]"></u-album> 這圖片路徑是我自己的 你們可以按照組件庫里面的方法去實現

DataFrame的使用

查看數據類型及屬性 # 查看df類型 type(df) # 查看df的shape屬性&#xff0c;可以獲取DataFrame的行數&#xff0c;列數 df.shape # 查看df的columns屬性&#xff0c;獲取DataFrame中的列名 df.columns # 查看df的dtypes屬性&#xff0c;獲取每一列的數據類型 df.dtypes df.i…

標準成本核算基礎知識 – 了解間接費用成本流程 - Part4

原文地址&#xff1a;Basics of Standard Costing – Understanding overhead cost flow-Part 4 | SAP Blogs 這是我理解標準成本計算及其流程的另一篇文檔的延續。 標準成本核算基礎知識 - 了解成本構成結構 - 第 3 部分 管理費用是只能間接歸因于產品的成本&#xff0c;例如…