歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux基礎 >> Linux教程 >> 對一個程序在內存中的分析

對一個程序在內存中的分析

日期:2017/2/28 15:55:31   编辑:Linux教程

內存管理是操作系統的核心;它對於程序員和系統管理員都很關鍵。在接下來的幾篇文章裡面我將對內存的關鍵技術做談論,但是不會遠離其本質。然而概念很普通,例子多半來自32位X86系統的LINUX和Window操作系統。這第一篇文章談論程序在內存中如何存放。

在多任務操作系統中的每一個進程運行在他自己的內存地址空間中。這個地址空間就是虛擬地址空間,虛擬地址空間在32位模式下總是4GB大小的內存地址。這些虛擬地址用頁表方式映射物理內存,頁表由操作系統內核維護,由處理器訪問。每個進程有自己的頁表集合,但這裡有個難以理解的地方。一旦虛擬地址(作者的意思也就是分頁機制)開啟,它應用與所有正在運行與機器上的軟件,包括內核自身。這樣一部分虛擬地址空間必須保留用於內核:

這並不意味著內核使用那麼多物理內存,只是他運用那部分可用的地址空間去映射他實際希望的物理內存大小。內核空間在頁表中標志為特權級代碼(等級小於等於2),這樣當用戶模式程序訪問他時就會觸發一個訪頁錯誤。在LINUX中,內核空間一直處於當前狀態並且在所有進程中映射到相同的物理內存。內核代碼和數據在任何時候總是為中斷服務和系統調用做好尋址的准備。相反,用於映射用戶模式的地址空間部分將會在進程切換的時候發生改變。

藍色區域代表已經映射物理內存的虛擬地址,白色區域為沒映射部分。在上面的例子中,Firefox由於他的巨大的內存需求,已經使用了他的大部分虛擬地址空間。地址空間中不同的帶對應內存段如堆、棧等等。需要注意的是這些段就是簡單的內存地址范圍,他和Intel匯編中的”段”不相干。下面是在LINUX進程中標准的段視圖:

當計算安全時,如上面的段所示,對於機器中的幾乎每一個進程的開始虛擬地址都相同。這使得很容易遠程利用安全漏洞。一個漏洞,往往需要引用絕對內存位置:棧上的地址,庫函數的地址,等等。遠程攻擊必須盲目地選擇這個內存位置,正指望這所有的地址空間都是一樣的。如果真是這樣,那麼太容易被攻擊了。故而地址空間的隨機化就變得通用了。LINUX以在棧、內存映射段和堆的起始地址加上偏移的方式隨機化他們。不幸的是,32位地址空間很緊缺,留下很少的空間用來做隨機化從而牽制了他的有效性。

進程地址空間中最上面的段為棧,很多語言中棧用於存儲本地變量和函數參數。調用一個方法或函數時壓入棧一個新的棧幀。當函數返回時,這個壓入的棧幀被釋放。這個簡單的設個,可能是因為數據遵循嚴格的FIFO次序,這意味著再復雜的數據結構都無需跟蹤棧內容——一個簡單的棧頂指針將會做跟蹤作用。這樣入棧和出棧非常快速和准確。進一步,堆棧地區不斷重用,往往在CPU緩存中持有活躍的棧內存,加快存取。進程中的每個線程獲得他自己的棧。

Copyright © Linux教程網 All Rights Reserved