首頁 > 軟體

Linux之程序的虛擬地址空間,邏輯地址和實體地址,程序管理命令

2023-03-23 22:07:01

程序的虛擬地址空間

程序有自己的獨立地址空間,每啟動一個程序,系統就會為它分配地址空間,虛擬地址空間的大小由計算機的硬體平臺決定,比如32位元的平臺決定了虛擬地址空間為4G(因為32位元系統上指標能夠定址的範圍是232

這4G空間的分配如下:

  • 由上圖可知,程序的虛擬記憶體被分為若干個“段”;
  • 每個段其實還被分成了若干個“塊”,我們將這個“塊”稱為“頁”;
  • 記憶體的對映(虛擬地址和實體地址之間的轉換)也是以“頁”為單位的;
  • 一般來說一頁的大小4K;
  • 交換空間(記憶體‘【這裡說的是實體記憶體】不夠時使用,把當前不使用的資料或者臨時資料放入到交換分割區中),在防止資料塊到交換分割區時,也是以"頁"為單位的,這個過程我們稱為“換出”,再由交換分割區調入記憶體,我們稱為“換入”,整個過程即為“換頁”

注意:虛擬地址一般由段號、頁號、頁中偏移量構成,從而最終計算出你的實體地址;

缺頁:消除了程序全部載入記憶體中,按需調頁(也就是換頁);

以上就是Linux的段頁式記憶體管理

1.核心空間(1G)

駐留在記憶體內,是作業系統的一部分,核心空間為核心保留,不允許應用程式讀寫該區域或呼叫核心程式碼。

2 棧(stack)

包括以下內容和用途:

  • 1 函數的返回值和引數。
  • 2 臨時變數,包括非靜態區域性變數,以及編譯器自動生成的臨時變數。
  • 3 儲存上下文:包括函數呼叫前後需保持不變的暫存器。

3 記憶體對映段(mmap)

該區域用於對映可執行檔案用到的動態連結庫。若可執行檔案依賴共用庫,則系統會為這些動態庫在從0x40000000開始的地址分配相應空間,並在程式裝載時將其載入到該空間。

在Linux 核心中,共用庫的起始地址被往上移動至更靠近棧區的位置。

4 堆(heap)

堆用於存放程序執行時動態分配的記憶體段,可動態擴張或縮減。堆中內容是匿名的,不能按名字直接存取,只能通過指標間接存取。

當程序呼叫malloc©/new(C++)等函數分配記憶體時,新分配的記憶體動態新增到堆上(擴張);當呼叫free©/delete(C++)等函數釋放記憶體時,被釋放的記憶體從堆中剔除(縮減) 。

5 .BSS段

.BSS(Block Started by Symbol)段中通常存放程式中以下符號:

  • 1 未初始化的全域性變數和靜態區域性變數
  • 2 初始值為0的全域性變數和靜態區域性變數(依賴於編譯器實現)
  • 3 未定義且初值不為0的符號(該初值即common block的大小)

6 資料段(.Data)

資料段通常用於存放程式中已初始化且初值不為0的全域性變數和靜態區域性變數。

資料段屬於靜態記憶體分配(靜態儲存區),可讀可寫。

7 程式碼段(text)

程式碼段也稱正文段或文欄位,通常用於存放程式執行程式碼(即CPU執行的機器指令)。一般C語言執行語句都編譯成機器程式碼儲存在程式碼段。

通常程式碼段是可共用的,因此頻繁執行的程式只需要在記憶體中擁有一份拷貝即可。

程式碼段通常屬於唯讀,以防止其他程式意外地修改其指令(對該段的寫操作將導致段錯誤)。

某些架構也允許程式碼段為可寫,即允許修改程式。

8 保留區

位於虛擬地址空間的最低部分,未賦予實體地址。

任何對它的參照都是非法的,用於捕捉使用空指標和小整型值指標參照記憶體的異常情況。

一個頁面的大小為4K(212),

——因此程序可以使用220個頁面

注:絕大多數處理器上的記憶體頁的預設大小都是 4KB,雖然部分處理器會使用 8KB、16KB 或者 64KB 作為預設的頁面大小,但是 4KB 的頁面仍然是作業系統預設記憶體頁設定的主流

邏輯地址

在某一段程式中,我們輸出的變數記憶體地址,其實是邏輯地址,也就是程序的地址空間。

虛擬地址向實體地址的轉換依靠的是記憶體管理單元(MMU)

有些時候,父子程序的某個變數的輸出地址可能相同,只可能是其邏輯地址相同,要想知道它們在記憶體中的實體地址,就必須根據邏輯地址判斷頁表號,再根據各自的頁表進行對映,找到其在記憶體中的具體位置,,不同程序的邏輯地址沒有可比性,但是如果在同一個程序中,若地址相同,那就證明其在同一段實體記憶體中。

如圖,在上述圖片中,假設父子程序的兩個變數的邏輯地址均為4097,那麼其就應該在頁表號為1的頁面上且偏移量為2(0-4095)的位置,在根據頁表號對映出其在實體記憶體中的真實地址。

為什麼我們在程式中不使用實體地址?

因為在執行程式的目標主機上,我們不知道當前哪些物理頁面是空閒的,如果我們程式寫的都是物理頁面,比如說,第一個程序說它要用0,1,2,3號頁面,假設其子程序也要用0,1,2,3號頁面,就衝突了,然後其他頁面是空閒的。我們在程式設計途中不知道其他程式會用哪些物理頁面,我們無法預知將要執行的主機上哪些物理頁面是空閒,而且物理頁面的空閒頁面是變化的,每次開機,空閒的頁面是不一樣的,我們無法確定,所以我們只能看邏輯地址,就像跳舞一樣,每個人有相對其他人的位置,跳舞的佇列是不變的,但是有可能在操場跳舞,或者在廣場跳舞。我們只能記錄相對位置,然後通過頁表對映,頁表的更新,確定哪個物理頁面是空閒的。

程序管理命令

pstree:樹狀結構顯示程序

ps:報告程式狀況

這一命令用來顯示某一時間點的程序資訊,這些資訊是靜態的,

若想檢視當前系統執行的動態程式資訊 可以使用top命令。

top:

下面列舉一些常用的選項:

ps -ef:顯示所有程式,並以ASCII字元顯示樹狀結構,表達程式間的相互關係

  • -e和-A的意思是一樣的,即顯示有關其他使用者程序的資訊,包括那些沒有控制終端的程序。
  • -f顯示使用者id,程序id,父程序id,最近CPU使用情況,程序開始時間等等

ps -l:長格式輸出

ps -aux:顯示當前終端所有程序(a)

注意與ps aux區分:列出正在執行的所有程序

使用者名稱 程序ID %CPU %記憶體 虛擬記憶體 固定記憶體 終端 狀態 起始時間 CPU時間 程式指令

ps -x:當前使用者在所有終端下的程序

ps -u:以使用者格式輸出

ps -elf:顯示系統內的所有程序

列名解釋:

如何殺死一個程序

  • kill  pid:結束pid程序
  • pkill:結束程序族
  • kill -9 pid:強制結束一個程序該,命令列可以使用`-9`引數來強制殺死程序

pkill sleep:可以結束後臺掛起的所用名叫sleep的程序

掛起是一種省電模式,系統將機器的硬碟,顯示器等外部裝置停止工作,而CPU,記憶體仍然在工作中,等待使用者隨時喚醒。

  • kill -stop pid:掛起一個程序
  •  jobs:檢視被掛起的程式工作號
  • command &:直接在後臺執行程式

用grep命令和kil命令結合殺死一個目標程序

如何在後臺執行一個程序 

命令+&

eg:

  • sleep 300&
  • sleep 300 &

程序恢復

  • fg 工作號:將掛起的作業放回到前臺執行
  • bg 工作號:將掛起的作業放到後臺執行

總結

以上為個人經驗,希望能給大家一個參考,也希望大家多多支援it145.com。


IT145.com E-mail:sddin#qq.com