windows和linux的記憶體管理

2021-08-25 01:30:34 字數 2810 閱讀 6140

windows的記憶體管理很是嚴謹,使用記憶體必須首先分配,當然每個作業系統都是這樣,然而windows的嚴謹在於分配的過程,分為保留和提交兩個階段,其中保留的含義就是在程序的虛擬位址空間保留一塊空間,不能用作他用,保留的概念是針對虛擬位址空間的,而提交的含義是將剛才保留的虛擬位址空間的虛擬記憶體塊對映到物理記憶體,這裡windows擴充套件了物理記憶體的含義,包括記憶體條代表的物理記憶體和磁碟頁檔案以及任何可以和真正的物理記憶體進行換入換出操作的後備儲存,提交的概念其實就是乙個對映,為了將虛擬記憶體變得可用而做的乙個到實際物理儲存的乙個對映,就是將假的變真了。

windows的保留和提交兩階段方式涉及到幾件事情,乙個就是頁表什麼時候確立,我們可以設想一種合理的方式,就是在記憶體塊保留的時候,不操作頁表,僅僅將虛擬記憶體段插入到乙個便於查詢和插入,刪除的資料結構中,而在提交階段操作頁表,當然此時記憶體不一定已經到了真正的物理記憶體,很有可能只在頁檔案中為之分配了乙個slot而已,此情形下,頁表的相關位就可以用來描述這個slot的位置以及別的資訊,只要頁表的存在位為0即可,這一點和linux可以一樣,事實上,提交記憶體只是在擴充套件物理記憶體含義的前提下才表示對映物理記憶體,虛擬記憶體真正被對映到原始物理記憶體只有在該記憶體被訪問的時候才會發生,這是絕對懶惰的。事實上我們可以看到windows的方式不夠懶惰,linux沒有保留和提交的概念,當乙個執行緒呼叫mmap或者malloc或者brk等等不同層次的函式時,實際上就等於保留了記憶體區域,而只有在該記憶體被訪問的時候,才會直接對映到物理記憶體而在這之前,根本不會將虛擬記憶體和物理的事實有任何聯絡,真對於假只有在不能再隱蔽事實的的時候才會顯露,linux的記憶體管理是一種絕對的懶惰,訪問記憶體其實就可以被看做記憶體提交。windows之所以採用這一種的方式來管理記憶體其實是為了用一種更加統一的方式去管理所有的記憶體,只要記憶體提交了,那麼記憶體管理器就要跟蹤這塊記憶體,不管它在物理儲存器還是在磁碟頁檔案。linux的方式看來更加不規範,linux使用頁表來充當雙面角色,既可以查詢物理儲存器又可以查詢交換分割槽記憶體的位置,並且linux中沒有一種機制來統一管理物理儲存器和交換分割槽的空間,靠強大的檔案系統功能和高效的記憶體管理和檔案管理資料結構就可以輕易做到記憶體的高效換入換出,解除了物理儲存器和交換分割槽的耦合,相反,在windows下,統一華麗的外表下扭曲著混亂不堪的繁雜,比如說如果想修改頁檔案的格式,那麼必須涉及記憶體提交時的邏輯,而在linux中只需要換乙個file_operations就可以了,統一華麗的外表完全不是僅僅帶來了觀感上的舒服,同樣也付出了代價,比如平衡程序間記憶體數量的任務就交給了使用者,其實使用者只要可以在本程序記憶體分配和管理記憶體上保持高度靈活就可以了,程序間的記憶體平衡這樣的任務顯然是作業系統應該擔負起來的,由於只要提交記憶體,或者在物理儲存器或者在磁碟頁檔案會佔據一定的空間,而這些空間是所有的程序共享的,如果乙個程序瘋狂的提交了過多的記憶體,那麼別的程序就要忍飢挨餓,這一點上作業系統作為乙個協調者實際上幫不上什麼忙,頂多將貪婪者滅掉了事,物理內存在各個程序間的分配比例完全取決於程序自己而失去了別的程序的監督以及核心機制的協調,這一點看起來不如linux,在linux中記憶體管理模組盡量使內存在程序間公平的分配,即使乙個程序自己分配了大量的記憶體,只要它不訪問這些記憶體,這些記憶體連交換分割槽都不會佔據更別說物理儲存器了,當然如果這個貪婪的程序要是訪問了這些記憶體,那結果就和windows一樣了,從程式的行為應該很容易辨別出這個程序,不過不管怎樣也比windows那種允許佔著茅坑不拉屎的策略要好得多,雖然記憶體已經很便宜,但是對於同樣增長的應用來講記憶體仍然是稀缺資源,因此完全懶惰式的分配方式應該就是最節省的方式。

作為以上討論的直接結果,我們來看一下兩個系統中的堆疊。在windows中堆疊的分配是靜態的,也就是說在pe檔案中確定了執行緒堆疊的大小並且一般不能在執行時動態改變,在對堆疊進行管理的時候,windows使用了一種稍微複雜一點但是考慮的很周到的方法,windows盡力去保護自己的堆疊不會溢位,怎麼保護呢?在《windows核心程式設計》上有詳細的描述,大致就是說首先為你的堆疊確定乙個大小,然後將這段如此大小的記憶體塊的第乙個和最後乙個頁面設定為保留,其餘的頁面遵循以下原則:假設堆疊向下增長,windows將依次把正在被使用的下乙個頁面設定為保護提交,當然正在被使用的頁面肯定是提交的了,每當保護提交頁面被訪問時系統會得到通知,注意得到通知而不是出錯資訊,並沒有什麼嚴重的錯誤,因為保護提交頁面可以被訪問,它已經提交了,只不過由於具有保護屬性,所有要告知系統這一件事,系統得知後可以將保護提交屬性設定給後乙個頁面,依次類推,堆疊有著嚴格的順序訪問特性,就是說首先是高位址被訪問,在略低的位址不被使用之前更低的位址不會被使用,當然除非你使用組合語言完全脫離堆疊的概念,這樣的話,執行緒的堆疊空間頁面將按照從高到底的順序乙個個被提交,而緊接著被提交的頁面將被設定為保護提交,直到最後,到達堆疊的末尾的時候,windows會檢測到,此時不再將最後乙個頁面設定為保護提交,而是引發乙個棧溢位異常。windows的這種機制的結果就是有效地保護了堆疊後面的資料不被堆疊資料覆蓋,但是這種機制並不是每次都奏效的,比如乙個足以使棧溢位的大陣列分配在棧上,陣列的起始其實已經出了堆疊,如果我直接訪問這第乙個元素的話,並且恰好該元素覆蓋的記憶體已經被提交,那就完蛋了,如果你覺得上述例項會被編譯器發現的話,那麼考慮下面的例子:

char s[1];

s -= 100000;

*s = 100;

看看linux是怎麼做的,很簡單,十分懶惰,linux沒有為堆疊分配靜態的大小,而是利用缺頁中斷使得堆疊在執行期動態增長,當然沒有了固定的大小也就不存在溢位的問題了,只要虛擬記憶體足夠,動態增長的需求就有可能被滿足,那麼linux有沒有什麼辦法來保護非堆疊資料被堆疊資料損壞或者反過來的情況呢?說實話,沒有,主要是因為一來實現那個機制很複雜,維護引入的額外資料結構肯定會影響效率,二來這是使用者空間的事情,程式設計師如果不合格直接開掉他就是了,核心不用為他擦屁股,實際上核心如果真的用雕蟲小技幫他擦了屁股,沒有會說核心很高明的,因此開源的linux沒有這種複雜而且單單對核心沒有什麼用的機制,實際上如果程式設計師不合格,那麼他寫的程式是防不勝防的,機器能和人pk嗎?很顯然不能,再好的作業系統面對一般爛的程式設計師也是無力去愛誰啊!

linux和windows的區別

linux和windows的區別 linux windows linux介面 windows 介面 圖形介面風格根據發布版不同而不同,可能互不相容。gun linux的終端機是從unix傳承下來的,基本命令和操作方法也幾乎一樣 介面統一外殼程式固定程式選單幾乎一致,快捷鍵也幾乎相同 linux操作 ...

linux和windows的區別

1.什麼是linux?linux是一套免費使用和自由傳播的類unix作業系統,是乙個多使用者 多工 支援多執行緒和多cpu的作業系統。它能執行主要的unix工具軟體 應用程式和網路協議。它支援32位和64位硬體。linux繼承了unix以網路為核心的設計思想,是乙個效能穩定的多使用者網路作業系統。2...

linux和windows的區別

目前國內linux更多的是應用於伺服器上,而桌面作業系統更多使用的是 windows。主要區別如下 比較windows linux 介面介面統一,外殼程式固定所有windows程式選單幾乎一致,快捷鍵也幾乎相同 圖形介面風格依發布版不同而不同,可能互不相容。gnu linux的終端機是從unix傳承...