1. 程式人生 > >Linux記憶體管理—詳細講解

Linux記憶體管理—詳細講解

`摘要:本章首先以應用程式開發者的角度審視Linux的程序記憶體管理,在此基礎上逐步深入到核心中討論系統實體記憶體管理和核心記憶體的使用方法。力求從外到內、水到渠成地引導網友分析Linux的記憶體管理與使用。在本章最後,我們給出一個記憶體對映的例項,幫助網友們理解核心記憶體管理與使用者記憶體管理之間的關係,希望大家最終能駕馭Linux記憶體管理。` ## 前言 ---   記憶體管理一向是所有作業系統書籍不惜筆墨重點討論的內容,無論市面上或是網上都充斥著大量涉及記憶體管理的教材和資料。因此,我們這裡所要寫的Linux記憶體管理採取避重就輕的策略,從理論層面就不去班門弄斧,貽笑大方了。我們最想做的和可能做到的是從開發者的角度談談對記憶體管理的理解,最終目的是把我們在核心開發中使用記憶體的經驗和對Linux記憶體管理的認識與大家共享。   當然,這其中我們也會涉及到一些諸如段頁等記憶體管理的基本理論,但我們的目的不是為了強調理論,而是為了指導理解開發中的實踐,所以僅僅點到為止,不做深究。   遵循“理論來源於實踐”的“教條”,我們先不必一下子就鑽入核心裡去看系統記憶體到底是如何管理,那樣往往會讓你陷入似懂非懂的窘境(我當年就犯了這個錯誤!)。所以最好的方式是先從外部(使用者程式設計範疇)來觀察程序如何使用記憶體,等到大家對記憶體的使用有了較直觀的認識後,再深入到核心中去學習記憶體如何被管理等理論知識。最後再通過一個例項程式設計將所講內容融會貫通。 ## 程序與記憶體 ### 程序如何使用記憶體???   毫無疑問,所有程序(處於執行態的程式)都必須佔用一定數量的記憶體,它或是用來存放從磁碟載入的程式程式碼,或是存放取自使用者輸入的資料等等。不過程序對這些記憶體的管理方式因記憶體用途不一而不盡相同,有些記憶體是事先靜態分配和統一回收的(如:靜態分配的資料,處於棧區,隨著所在的生命週期結束而被釋放),而有些卻是按需要動態分配和回收的(如:動態分配的資料,處於堆區,必須由程式設計師自己釋放否則將會造成記憶體洩漏等結果)。   對任何一個普通程序來講,它都會涉及到5種不同的資料段。稍有程式設計知識的朋友都能想到這幾個資料段中包含有“程式程式碼段”、“程式資料段”、“程式堆疊段”等。不錯,這幾種資料段都在其中,但除了以上幾種資料段之外,程序還另外包含兩種資料段。下面我們來簡單歸納一下程序對應的記憶體空間中所包含的5種不同的資料區。 **程式碼段**:程式碼段是用來存放可執行檔案的操作指令,也就是說是它是可執行程式在記憶體中的映象。程式碼段需要防止在執行時被非法修改,所以只准許讀取操作,而不允許寫入(修改)操作——注:它是不可寫的。 **資料段**:資料段用來存放可執行檔案中已初始化全域性變數,換句話說就是存放程式靜態分配的變數和全域性變數。 **BSS段**:BSS段包含了程式中未初始化的全域性變數,在記憶體中 bss段全部置零。 **堆(heap)**:堆是用於存放程序執行中被動態分配的記憶體段,它的大小並不固定,可動態擴張或縮減。當程序呼叫malloc等函式分配記憶體時,新分配的記憶體就被動態新增到堆上(堆被擴張);當利用free等函式釋放記憶體時,被釋放的記憶體從堆中被剔除(堆被縮減)。 **棧(stack)**:棧是使用者存放程式臨時建立的區域性變數,也就是說我們函式括弧“{}”中定義的變數(但不包括static宣告的變數,static意味著在資料段中存放變數)。除此以外,在函式被呼叫時,其引數也會被壓入發起呼叫的程序棧中,並且待到呼叫結束後,函式的返回值也會被存放回棧中。由於棧的先進先出特點,所以棧特別方便用來儲存/恢復呼叫現場。從這個意義上講,我們可以把堆疊看成一個寄存、交換臨時資料的記憶體區。 ### 程序如何組織這些區域?   上述幾種記憶體區域中資料段、BSS和堆通常是被連續儲存的——記憶體位置上是連續的,而程式碼段和棧往往會被獨立存放。有趣的是,堆和棧兩個區域關係很“曖昧”(如同[牛郎織女在雀橋相會那樣的情景](https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=355731407,758394793&fm=27&gp=0.jpg)),他們一個向下“長”(i386體系結構中棧向下、堆向上),一個向上“長”,相對而生。但你不必擔心他們會碰頭,因為他們之間間隔很大(到底大到多少,你可以從下面的例子程式計算一下),絕少有機會能碰到一起。 “事實勝於雄辯”,我們用一個小例子(原形取自《User-Level Memory Management》)來展示上面所講的各種記憶體區的差別與位置。 ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20191024175457336.png) ~~~c