一 、前言算法
這篇文章簡單介紹操做系統的內存管理機制,包括動態分區分配,分頁,分段和段頁式。編程
2、動態分區內存數組
給了一塊很大的內存,如何寫一個new和delete作內存分配。雖然這個問題源自於操做系統的內存管理,但如今操做系統基本都用段頁式了。而動態分區內存的思路主要用來寫程序中的動態申請和回收內存了。緩存
須要一個空閒分區表,記錄每一個分區是否分配,分區起址,分區長度。數據結構
還須要空閒分區鏈,把多個分區連接起來。函數
(在實現new和delete時並無用這樣的結構,而是用了相似靜態鏈表的結構)優化
內存分配和回收spa
1 起始時內存分區只有一個,是一塊很大的內存。進程建立時,從中劃分出一塊分給進程,剩下的放回空閒分區鏈中。操作系統
2 當進程終止,把內存回收,掛到空閒分區鏈中,按起始地址排序。3d
3 能夠想一想通過屢次分配和回收空閒分區鏈會有不少分區,分配內存須要必定策略。首次適應算法、循環首次適應算法、最佳適應算法、最壞適應算法、快速適應算法。
4 因爲這種分配,可能產生不少外碎片。也有在回收時合併分區的策略:
回收區與插入點的前一個空閒分區F1相鄰接,此時將兩個分區合併
回收區與插入點的後一個空閒分區F2相鄰接,此時將兩個分區合併
回收區與插入點的前,後兩個空閒分區相鄰接,此時將三個分區合併
回收區既不與F1相鄰接,又不與F2相鄰接,此時應爲回收區單獨創建一個新表項
5 也能夠引入夥伴系統來優化碎片。按2的冪的大小分配和回收內存,這樣分配和回收均可能遞歸的劃分/合併夥伴。會產生一些內碎片。
6能夠根據抖動來判斷一個內存管理系統的好壞。
保護:經過進程上下界來方式越界。
3、分頁
神器的百度百科竟然有課本上的內容,搜 基本分頁存儲管理方式、基本分段存儲管理方式、段頁式存儲管理方式
分配和回收
分頁存儲管理是將一個進程的邏輯地址空間分紅若干個大小相等的片,稱爲頁面或頁;相應地,也把內存空間分紅與頁面相同大小的若干個存儲塊,稱爲(物理)塊或頁框(frame)。塊的大小通常是512B~8KB。
用一個bit數組(位示圖)標識內存的每一個塊是否已被分配。分配時找到一個未分配的空間分配,bit數組置1;回收時bit數組置0。關於分配和回收還要改一下頁表。
地址變換
1 看按箭頭的方向看這張圖。開始的時候是一個邏輯地址,就是程序中的地址。結果是一個物理地址,就是內存中的地址。好比說程序中的函數在2500號的位置,頁大小是1024,則通過編譯器編譯後獲得的邏輯地址是頁號爲2500/1024=2,頁內地址爲2500 % 1024=452。而物理地址也由兩部分組成,塊號(暫時還不知道是多少),塊內地址是452。
2 由頁號怎麼獲得塊號,內存中用頁表來記錄這種映射。好比說一個進程有100個頁,當這個進程建立,頁表中就加100項,每項對應於進程的頁到內存塊的映射。
3 操做系統只有一個頁表,被多進程公用。因此每一個進程在頁表中的key(頁號)是連續存放,另外在訪問頁表前要知道進程對應的key在頁表中的起始位置,還要知道在頁表中的長度(好比說前面的100)。起始位置和頁表長度放在進程的PCB裏,在進程調度後,放到頁表寄存器中。根據這兩個值就能在頁表中找到頁的位置了~~。
4 由3知道,頁號不用存放在頁表中,因此頁表就是如圖的塊號數組。
因爲頁表用內存實現,因此在訪問物理地址前,就要訪問多一次內存(讀頁表)。因而加入了快表來優化,快表是一個硬件實現,用寄存器。用於緩存當前進程最近使用的頁-塊映射記錄。
存儲保護:見圖中有頁號的越界處理。
碎片:每一個進程末尾會有一點頁內碎片。
虛擬存儲:
4、分段
宗旨是進程是分段的,簡單來講就是快成若干個模塊,有調用過動態連接庫就很容易理解這一點。按用戶的編程需求,分段更天然。固然這裏講分段和前面的分頁都是基礎,操做系統都是用段頁式的~~
分配和回收:相似於動態分區內存。只不過進程調度時,一次要載入若干個段,而不是整個進程載入。
地址變換:看完分頁,這個一看就懂。
保護同分頁;
碎片同動態分區內存。
5、段頁式
有了分段,分頁,段頁式就簡單了,一圖流
6、交換相關策略
交換過程當中涉及不少策略
分配多少內存給進程:首先能夠肯定最小物理塊數,以後還有一些其餘策略。
何時調入頁面:
預調入:若是進程的許多頁是存放在外存的一個連續區域中,則一次調入若干相鄰的頁,會比一次調入一個頁更高效些。
請求調入:缺頁時再調入
調入的頁來自哪裏:因爲與進程有關的文件都放在文件區,故凡是未運行過的頁面,都應從文件區調入。而對於曾經運行過但又被換出的頁面,因爲是被放在對換區,所以在下次調入時,應從對換區調入。因爲UNIX系統容許頁面共享,所以,某進程所請求的頁面有可能已被其它進程調入內存,此時也就無須再從對換區調入。
內存滿的時候淘汰哪一個頁面(頁面置換算法):
假定系統爲某進程分配了三個物理塊,並考慮有如下的頁面號引用串:
7,0,1,2,0,3,0,4,2,3,0,3,2,1,2,0,1,7,0,1
最佳(Optimal)置換算法
先進先出(FIFO)置換算法
最近最久未使用(LRU)置換算法:按上次使用的時間排序,時間最先的一個頁被淘汰
Clock置換算法:設置兩個位,最近訪問位A和,被修改位M。被訪問了的頁A置爲1;淘汰時若是被掃描掃中,若是A=1,把A置爲0。不然直接淘汰。
掃描淘汰時,會按AM由00~11的順序掃描。
最少使用(LFU)置換算法:以最近的使用次時排序。實際上的作法是每次使用把排序值的最高位置1,每隔一段時間把排序值右移。
虛擬內存的原理是局部性原理。
7、總結
看一個內存管理機制其實就是看它的數據結構、分配和回收、地址變換、虛擬存儲、存儲保護、信息共享、碎片管理。
地址變換:這是指編程時寫的地址怎麼變換成內存地址。這個概念是因爲做業分塊纔有的。在動態分區分配等方式中,做業是最小的處理單元,編程地址只要是相對做業的起始便可。而在分頁,分段中,做業有更小的處理單元,因此地址變換就更復雜。
虛擬存儲:如何用小的空間模擬大的空間。有覆蓋和交換兩種技術。覆蓋有點像c語言的空間共用,union。而交換就是把內存中不經常使用的換到外存。只有分頁和分段才能交換,由於它們的粒度更小,能夠換。
存儲保護:防止程序越界訪問其餘程序的內存空間。
信息共享:好比說動態連接庫,能夠在多個進程間共享。
最後列幾個相關的概念:
靜態重定位是在程序執行以前進行重定位,它根據裝配模塊將要裝入的內存起始位置,直接修改裝配模塊中的有關使用地址的指令。
動態重定位是指,不是在程序執行以前而是在程序執行過程當中進行地址重定位。更確切地說,是在CPU每次訪問內存單元前才進行地址變換。