自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

深入理解Linux中內(nèi)存管理

系統(tǒng) Linux
本文記錄了作者自己對Linux系統(tǒng)中內(nèi)存管理的一些理解和看法,從Linux內(nèi)存管理中的分段和分頁技術(shù)方面進(jìn)行了分析,以便于大家理解。

前一段時(shí)間看了《深入理解Linux內(nèi)核》對其中的內(nèi)存管理部分花了不少時(shí)間,但是還是有很多問題不是很清楚,最近又花了一些時(shí)間復(fù)習(xí)了一下,在這里記錄下自己的理解和對Linux中內(nèi)存管理的一些看法和認(rèn)識。

我比較喜歡搞清楚一個(gè)技術(shù)本身的發(fā)展歷程,簡而言之就是這個(gè)技術(shù)是怎么發(fā)展而來的,在這個(gè)技術(shù)之前存在哪些技術(shù),這些技術(shù)有哪些特點(diǎn),為什么會(huì)被目前的技術(shù)所取代,而目前的技術(shù)又解決了之前的技術(shù)所存在的哪些問題。弄清楚了這些,我們才能比較清晰的把握某一項(xiàng)技術(shù)。有些資料在介紹某個(gè)概念的時(shí)候直接就介紹這個(gè)概念的意義,原理,而對其發(fā)展過程和背后的原理絲毫不提,仿佛這個(gè)技術(shù)從天上掉下來的一樣。介于此,還是以內(nèi)存管理的發(fā)展歷程來講述今天的主題。

首先,我必須要闡述一下這篇文章的主題是Linux內(nèi)存管理中的分段和分頁技術(shù)。

讓我們來回顧一下歷史,在早期的計(jì)算機(jī)中,程序是直接運(yùn)行在物理內(nèi)存上的。換句話說,就是程序在運(yùn)行的過程中訪問的都是物理地址。如果這個(gè)系統(tǒng)只運(yùn)行一個(gè)程序,那么只要這個(gè)程序所需的內(nèi)存不要超過該機(jī)器的物理內(nèi)存就不會(huì)出現(xiàn)問題,我們也就不需要考慮內(nèi)存管理這個(gè)麻煩事了,反正就你一個(gè)程序,就這么點(diǎn)內(nèi)存,吃不吃得飽那是你的事情了。然而現(xiàn)在的系統(tǒng)都是支持多任務(wù),多進(jìn)程的,這樣CPU以及其他硬件的利用率會(huì)更高,這個(gè)時(shí)候我們就要考慮到將系統(tǒng)內(nèi)有限的物理內(nèi)存如何及時(shí)有效的分配給多個(gè)程序了,這個(gè)事情本身我們就稱之為內(nèi)存管理。

下面舉一個(gè)早期的計(jì)算機(jī)系統(tǒng)中,內(nèi)存分配管理的例子,以便于大家理解。

加入我們有三個(gè)程序,程序1,2,3.程序1運(yùn)行的過程中需要10M內(nèi)存,程序2運(yùn)行的過程中需要100M內(nèi)存,而程序3運(yùn)行的過程中需要20M內(nèi)存。如果系統(tǒng)同時(shí)需要運(yùn)行程序A和B,那么早期的內(nèi)存管理過程大概是這樣的,將物理內(nèi)存的前10M分配給A, 接下來的10M-110M分配給B。這種內(nèi)存管理的方法比較直接,好了,假設(shè)我們這個(gè)時(shí)候想讓程序C也運(yùn)行,同時(shí)假設(shè)我們系統(tǒng)的內(nèi)存只有128M,顯然按照這種方法程序C由于內(nèi)存不夠是不能夠運(yùn)行的。大家知道可以使用虛擬內(nèi)存的技術(shù),內(nèi)存空間不夠的時(shí)候可以將程序不需要用到的數(shù)據(jù)交換到磁盤空間上去,已達(dá)到擴(kuò)展內(nèi)存空間的目的。下面我們來看看這種內(nèi)存管理方式存在的幾個(gè)比較明顯的問題。就像文章一開始提到的,要很深層次的把握某個(gè)技術(shù)***搞清楚其發(fā)展歷程。

1.進(jìn)程地址空間不能隔離

由于程序直接訪問的是物理內(nèi)存,這個(gè)時(shí)候程序所使用的內(nèi)存空間不是隔離的。舉個(gè)例子,就像上面說的A的地址空間是0-10M這個(gè)范圍內(nèi),但是如果A中有一段代碼是操作10M-128M這段地址空間內(nèi)的數(shù)據(jù),那么程序B和程序C就很可能會(huì)崩潰(每個(gè)程序都可以系統(tǒng)的整個(gè)地址空間)。這樣很多惡意程序或者是木馬程序可以輕而易舉的破快其他的程序,系統(tǒng)的安全性也就得不到保障了,這對用戶來說也是不能容忍的。

2. 內(nèi)存使用的效率低

如上面提到的,如果我們要像讓程序A、B、C同時(shí)運(yùn)行,那么唯一的方法就是使用虛擬內(nèi)存技術(shù)將一些程序暫時(shí)不用的數(shù)據(jù)寫到磁盤上,在需要的時(shí)候再從磁盤讀回內(nèi)存。這里程序C要運(yùn)行,將A交換到磁盤上去顯然是不行的,因?yàn)槌绦蚴切枰B續(xù)的地址空間的,程序C需要20M的內(nèi)存,而A只有10M的空間,所以需要將程序B交換到磁盤上去,而B足足有100M,可以看到為了運(yùn)行程序C我們需要將100M的數(shù)據(jù)從內(nèi)存寫到磁盤,然后在程序B需要運(yùn)行的時(shí)候再從磁盤讀到內(nèi)存,我們知道IO操作比較耗時(shí),所以這個(gè)過程效率將會(huì)十分低下。

3. 程序運(yùn)行的地址不能確定

程序每次需要運(yùn)行時(shí),都需要在內(nèi)存中非配一塊足夠大的空閑區(qū)域,而問題是這個(gè)空閑的位置是不能確定的,這會(huì)帶來一些重定位的問題,重定位的問題確定就是程序中引用的變量和函數(shù)的地址,如果有不明白童鞋可以去查查編譯愿意方面的資料。

內(nèi)存管理無非就是想辦法解決上面三個(gè)問題,如何使進(jìn)程的地址空間隔離,如何提高內(nèi)存的使用效率,如何解決程序運(yùn)行時(shí)的重定位問題?

這里引用計(jì)算機(jī)界一句無從考證的名言:“計(jì)算機(jī)系統(tǒng)里的任何問題都可以靠引入一個(gè)中間層來解決。”

現(xiàn)在的內(nèi)存管理方法就是在程序和物理內(nèi)存之間引入了虛擬內(nèi)存這個(gè)概念。虛擬內(nèi)存位于程序和屋里內(nèi)存之間,程序只能看見虛擬內(nèi)存,再也不能直接訪問物理內(nèi)存。每個(gè)程序都有自己獨(dú)立的進(jìn)程地址空間,這樣就做到了進(jìn)程隔離。這里的進(jìn)程地址空間是指虛擬地址。顧名思義既然是虛擬地址,也就是虛的,不是現(xiàn)實(shí)存在的地址空間。

既然我們在程序和物理地址空間之間增加了虛擬地址,那么就要解決怎么從虛擬地址映射到物理地址,因?yàn)槌绦蜃罱K肯定是運(yùn)行在物理內(nèi)存中的,主要有分段和分頁兩種技術(shù)。

分段(Segmentation):這種方法是人們最開始使用的一種方法,基本思路是將程序所需要的內(nèi)存地址空間大小的虛擬空間映射到某個(gè)
物理地址空間。

段映射機(jī)制

每個(gè)程序都有其獨(dú)立的虛擬的獨(dú)立的進(jìn)程地址空間,可以看到程序A和B的虛擬地址空間都是從0x00000000開始的。我們將兩塊大小相同的虛擬地址空間和實(shí)際物理地址空間一一映射,即虛擬地址空間中的每個(gè)字節(jié)對應(yīng)于實(shí)際地址空間中的每個(gè)字節(jié),這個(gè)映射過程由軟件來設(shè)置映射的機(jī)制,實(shí)際的轉(zhuǎn)換由硬件來完成。

這種分段的機(jī)制解決了文章一開始提到的3個(gè)問題中的進(jìn)程地址空間隔離和程序地址重定位的問題。程序A和程序B有自己獨(dú)立的虛擬地址空間,而且該虛擬地址空間被映射到了互相不重疊的物理地址空間,如果程序A訪問虛擬地址空間的地址不在0x00000000-0x00A00000這個(gè)范圍內(nèi),那么內(nèi)核就會(huì)拒絕這個(gè)請求,所以它解決了隔離地址空間的問題。我們應(yīng)用程序A只需要關(guān)心其虛擬地址空間0x00000000-0x00A00000,而其被映射到哪個(gè)物理地址我們無需關(guān)心,所以程序永遠(yuǎn)按照這個(gè)虛擬地址空間來放置變量,代碼,不需要重新定位。

無論如何分段機(jī)制解決了上面兩個(gè)問題,是一個(gè)很大的進(jìn)步,但是對于內(nèi)存效率問題仍然無能為力。因?yàn)檫@種內(nèi)存映射機(jī)制仍然是以程序?yàn)閱挝?,?dāng)內(nèi)存不足時(shí)仍然需要將整個(gè)程序交換到磁盤,這樣內(nèi)存使用的效率仍然很低。那么,怎么才算高效率的內(nèi)存使用呢。事實(shí)上,根據(jù)程序的局部性運(yùn)行原理,一個(gè)程序在運(yùn)行的過程當(dāng)中,在某個(gè)時(shí)間段內(nèi),只有一小部分?jǐn)?shù)據(jù)會(huì)被經(jīng)常用到。所以我們需要更加小粒度的內(nèi)存分割和映射方法,此時(shí)是否會(huì)想到Linux中的Buddy算法和slab內(nèi)存分配機(jī)制呢,哈哈。另一種將虛擬地址轉(zhuǎn)換為物理地址的方法分頁機(jī)制應(yīng)運(yùn)而生了。

分頁機(jī)制:

分頁機(jī)制就是把內(nèi)存地址空間分為若干個(gè)很小的固定大小的頁,每一頁的大小由內(nèi)存決定,就像Linux中ext文件系統(tǒng)將磁盤分成若干個(gè)Block一樣,這樣做是分別是為了提高內(nèi)存和磁盤的利用率。試想以下,如果將磁盤空間分成N等份,每一份的大小(一個(gè)Block)是1M,如果我想存儲(chǔ)在磁盤上的文件是1K字節(jié),那么其余的999字節(jié)是不是浪費(fèi)了。所以需要更加細(xì)粒度的磁盤分割方式,我們可以將Block設(shè)置得小一點(diǎn),這當(dāng)然是根據(jù)所存放文件的大小來綜合考慮的,好像有點(diǎn)跑題了,我只是想說,內(nèi)存中的分頁機(jī)制跟ext文件系統(tǒng)中的磁盤分割機(jī)制非常相似。

Linux中一般頁的大小是4KB,我們把進(jìn)程的地址空間按頁分割,把常用的數(shù)據(jù)和代碼頁裝載到內(nèi)存中,不常用的代碼和數(shù)據(jù)保存在磁盤中,我們還是以一個(gè)例子來說明,如下圖:


進(jìn)程虛擬地址空間、物理地址空間和磁盤之間的頁映射關(guān)系

我們可以看到進(jìn)程1和進(jìn)程2的虛擬地址空間都被映射到了不連續(xù)的物理地址空間內(nèi)(這個(gè)意義很大,如果有一天我們的連續(xù)物理地址空間不夠,但是不連續(xù)的地址空間很多,如果沒有這種技術(shù),我們的程序就沒有辦法運(yùn)行),甚至他們共用了一部分物理地址空間,這就是共享內(nèi)存。

進(jìn)程1的虛擬頁VP2和VP3被交換到了磁盤中,在程序需要這兩頁的時(shí)候,Linux內(nèi)核會(huì)產(chǎn)生一個(gè)缺頁異常,然后異常管理程序會(huì)將其讀到內(nèi)存中。

這就是分頁機(jī)制的原理,當(dāng)然Linux中的分頁機(jī)制的實(shí)現(xiàn)還是比較復(fù)雜的,通過了也全局目錄,也上級目錄,頁中級目錄,頁表等幾級的分頁機(jī)制來實(shí)現(xiàn)的,但是基本的工作原理是不會(huì)變的。

分頁機(jī)制的實(shí)現(xiàn)需要硬件的實(shí)現(xiàn),這個(gè)硬件名字叫做MMU(Memory Management Unit),他就是專門負(fù)責(zé)從虛擬地址到物理地址轉(zhuǎn)換的,也就是從虛擬頁找到物理頁。

原文鏈接:http://blog.chinaunix.net/uid-26611383-id-3761754.html

責(zé)任編輯:黃丹 來源: 博客
相關(guān)推薦

2022-11-09 08:12:07

2023-12-31 12:56:02

C++內(nèi)存編程

2023-11-05 12:05:35

JVM內(nèi)存

2022-08-21 16:52:27

Linux虛擬內(nèi)存

2022-11-21 09:09:08

Linux物理內(nèi)存管理

2023-09-19 22:47:39

Java內(nèi)存

2020-11-04 15:35:13

Golang內(nèi)存程序員

2023-02-10 08:11:43

Linux系統(tǒng)調(diào)用

2022-10-24 08:48:07

虛擬內(nèi)存Linux

2022-12-28 09:07:41

2025-03-28 08:35:00

2021-11-26 00:00:48

JVM內(nèi)存區(qū)域

2022-07-06 08:05:52

Java對象JVM

2015-12-28 11:41:57

JVM內(nèi)存區(qū)域內(nèi)存溢出

2021-08-31 10:32:11

LinuxPage Cache命令

2010-06-01 15:25:27

JavaCLASSPATH

2016-12-08 15:36:59

HashMap數(shù)據(jù)結(jié)構(gòu)hash函數(shù)

2020-07-21 08:26:08

SpringSecurity過濾器

2024-07-18 10:12:04

2013-11-05 13:29:04

JavaScriptreplace
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號