作為一個程序員,至少對操作系統(tǒng)是要有些了解的,最近被問了幾次,主要是內存分配算法的實現(xiàn)思路,其實這次過來復習不過是為了熟悉專業(yè)名詞。正如上次被問到LRU,主要是不知道這東西是什么?
也發(fā)現(xiàn)其實關于線程的實現(xiàn),其實當年學過...
連續(xù)內存分配
最先匹配:First Fit Allocation
-
原理與實現(xiàn):
- 空閑分區(qū)列表按地址順序排序
- 分配過程時,搜索一個合適的分區(qū)
- 釋放分區(qū)時,檢查是否可與臨近的空閑分區(qū)合并
-
優(yōu)點:
- 簡單
- 在高地址空間有大塊的空閑分區(qū)
-
缺點:
- 外部碎片
- 分配大塊時較慢

最佳匹配:Best Fit Allocation
思路:分配n字節(jié)分區(qū)時, 查找并使用不小于n的最小空閑分區(qū)
- 原理與實現(xiàn)
- 空閑分區(qū)列表按照大小排序
- 分配時,查找一個合適的分區(qū)
- 釋放時,查找并且合并臨近的空閑分區(qū)(如果找到)
- 優(yōu)點
- 大部分分配的尺寸較小時,效果很好
- 可避免大的空閑分區(qū)被拆分
- 可減小外部碎片的大小
- 相對簡單
- 缺點
- 外部碎片
- 釋放分區(qū)較慢,合并相鄰分區(qū)的工作并不容易處理
- 容易產生很多無用的小碎片
最差匹配: Worst Fit Allocation
思路:分配n字節(jié),使用尺寸不小于n的最大空閑分區(qū)

-
原理與實現(xiàn)
- 空閑分區(qū)列表按由大到小排序
- 分配時,選最大的分區(qū)
- 釋放時,檢查是否可與臨近的空閑分區(qū)合并,進行可能的合并,并調整空閑分區(qū)列表順序
-
優(yōu)點
- 中等大小的分配較多時,效果最好
- 避免出現(xiàn)太多的小碎片
-
缺點
- 釋放分區(qū)較慢
- 外部碎片
- 容易破壞大的空閑分區(qū),因此后續(xù)難以分配大的分區(qū)
連續(xù)內存分配的缺點:
- 分配給程序的物理內存必須連續(xù)
- 存在外部碎片和內部碎片
- 內存分配的動態(tài)修改困難
- 內存利用率較低
非連續(xù)內存
段地址空間
更細粒度和靈活的分離與共享
進程的段地址空間由多個段組成:
- 主代碼段
- 子模塊代碼段
- 公用庫代碼段
- 堆棧段(stack)
- 堆數(shù)據(jù)(heap)
- 初始化數(shù)據(jù)段
- 符號表等
- 段的概念
- 段表示
訪問方式和存儲數(shù)據(jù)等屬性相同的一段地址空間 - 對應一個連續(xù)的內存“塊”
- 若干個段組成進程邏輯地址空間
- 段表示
- 段訪問:邏輯地址由二元組(s, addr)表示
- s:段號
- addr:段內偏移
頁式存儲管理
- 頁幀(幀、物理頁面, Frame, Page Frame)
- 把物理地址空間劃分為大小相同的基本分配單位 ,$2^n$,如512, 4096, 8192
- 頁面(頁、邏輯頁面, Page)
- 把邏輯地址空間也劃分為相同大小的基本分配單位
- 頁面到頁幀
- 邏輯地址到物理地址的轉換
- 頁表
- MMU/TLB
幀 (Frame):
物理內存被劃分成大小相等的幀
內存物理地址的表示:二元組 (f, o)
- f :幀號 (F 位, 共有$2^F$ 個幀)
- o:幀內偏移 (S 位, 每幀有$2^S$ 字節(jié))
- 物理地址:$f * 2^S + o$
頁(Page)
進程邏輯地址空間被劃分為大小相等的頁
頁內偏移 = 幀內偏移
通常:頁號大小 ≠ 幀號大小
進程邏輯地址的表示:二元組 (p, o)
- p:頁號 (P 位, $2^P$ 個頁)
- o:頁內偏移 (S 位, 每頁有$2^S$ 字節(jié))
- 虛擬地址 $= p * 2^S + o $
頁式存儲中的地址映射
頁到幀的映射:邏輯地址中的頁號是連續(xù)的,映射到物理地址中的物理幀號就變成是不連續(xù)的
頁表
- 頁表保存了邏輯地址到物理地址之間的映射關系
- 每個進程擁有一個頁表,隨著進程的變化而變化
頁式存儲管理機制的性能問題
- 訪問一個內存單元需要2次內存訪問
- 第一次訪問:獲取頁表項
- 第二次訪問:訪問數(shù)據(jù)
- 頁表大小問題:
- 頁表可能非常大
- 64位機器如果每頁1024字節(jié),那么一個頁表的大小會是多少?
- 如何處理?
- 緩存(Caching)
- 間接(Indirection)訪問
段頁式存儲管理
在段式存儲管理基礎上,給每個段加一級頁表
頁置換
場景:內存里所有幀都被分配了,無法將虛擬內存中的頁映射到新的幀上
使用修改位,只有修改過的才被回寫到硬盤
頁置換的基本方法
- 查找所需頁在磁盤上的位置(假設頁已經被寫到磁盤)
- 查找一空閑幀
- 如果有空閑幀,那么就使用它
- 如果沒有空閑幀,那么就使用頁置換算法以選擇一個“犧牲”幀(victim frame)。
- 將“犧牲”幀的內容寫到磁盤上(如果是臟頁);改變頁表和幀表。
- 將所需頁讀入(新)空閑幀;改變頁表和幀表
- 重啟用戶進程。
頁面置換算法
-
局部頁面置換算法--------->當前進程占用的物理頁面內
- 最優(yōu)算法、先進先出算法、最近最久未使用算法
- 時鐘算法、最不常用算法
-
全局頁面置換算法-------->所有可換出的物理頁面
- 工作集算法、缺頁率算法
最優(yōu)頁面置換算法(OPT, Optimal)
基本思路: 置換在未來最長時間不訪問的頁面
-
算法實現(xiàn):
- 缺頁時,計算內存中每個邏輯頁面的下一次訪問時間(無法計算)
- 選擇未來最長時間不訪問的頁面
-
算法特征
- 缺頁最少,是理想情況
- 實際系統(tǒng)中無法實現(xiàn), 無法預知每個頁面在下次訪問前的等待時間
- 作為置換算法的性能評價依據(jù)
先進先出算法(FIFO)
思路: 選擇在內存駐留時間最長的頁面進行置換
-
實現(xiàn): 優(yōu)先隊列。堆排序,鏈表實現(xiàn)
- 維護一個記錄所有位于內存中的邏輯頁面鏈表:
- 鏈表元素按駐留內存的時間排序,鏈首最長,鏈尾最短
- 出現(xiàn)缺頁時,選擇鏈首頁面進行置換,新頁面加到鏈尾
-
特征
- 實現(xiàn)簡單
- 性能較差,調出的頁面可能是經常訪問的
- 進程分配物理頁面數(shù)增加時,缺頁并不一定減少Belady[1]現(xiàn)象
- 很少單獨使用
最近最久未使用算法(LRU)
LRU: Least Recently Used
-
思路
- 選擇最長時間沒有被引用的頁面進行置換
- 如某些頁面長時間未被訪問,則它們在將來還可能會長時間不會訪問。
-
實現(xiàn)
- 缺頁時,計算內存中每個邏輯頁面的上一次訪問時間
- 選擇上一次使用到當前時間最長的頁面
-
特征
- 最優(yōu)置換算法的一種近似,最優(yōu)置換是基于未來可知的。
- 這里認為未來是過去的一種延續(xù),是基于過去的。
- 每次使用完就把這個頁放到堆頂,把其他的頁往后挪。這里應該是鏈表實現(xiàn)。
- 缺頁就置換最后那個頁。
- 開銷比較大,很少計算機系統(tǒng)支持真正的LRU算法
時鐘置換算法(Clock)
-
思路
- 僅對頁面的訪問情況進行大致統(tǒng)計
-
數(shù)據(jù)結構
- 在頁表項中增加訪問位(reference bit),描述頁面在過去一段時間的內訪問情況
- 各頁面組織成環(huán)形鏈表(循環(huán)隊列)
- 指針指向最先調入的頁面
-
算法
- 訪問頁面時,在頁表項記錄頁面訪問情況
- 缺頁時,從指針處開始順序查找未被訪問的頁面進行置換
-
特征
- 時鐘算法是LRU和FIFO的折中
-
時鐘置換算法的實現(xiàn)
- 頁面裝入內存時,訪問位初始化為0
- 訪問頁面(讀 寫 時,訪問位 置1
- 缺頁時,從指針當前位置順序檢查環(huán)形鏈表
- 訪問位為0 ,則置換該頁
- 訪問位為 1,則訪問位 置1 (相當于給該頁第二次機會),并指針移動到下一個頁面,直到找到可置換的頁面
- 所以也叫二次機會算法(Second chance Algorithm)
最不常用算法(LFU)
LFU: Least Frequently Used
- 思路
- 缺頁時,置換訪問次數(shù)最少的頁面
- 實現(xiàn)
- 每個頁面設置一個訪問計數(shù)
- 訪問頁面時,訪問計數(shù)加
- 缺頁時,置換計數(shù)最小的頁面
- 特征
- 算法開銷大
- 開始時頻繁使用,但以后不使用的頁面很難置換
- 解決方法:計數(shù)定期右移(即計數(shù)減半)
- LRU和LFU的區(qū)別
- LRU關注多久未訪問,LFU關注訪問次數(shù)
LRU、FIFO的比較
LRU依據(jù)頁面的最近訪問時間排序
LRU需要動態(tài)地調整順序
FIFO依據(jù)頁面進入內存的時間排序
FIFO的頁面進入時間是固定不變的
LRU可退化成FIFO
LRU、FIFO和Clock的比較
- LRU算法性能較好,但系統(tǒng)開銷較大。(需要維護優(yōu)先隊列)
- FIFO算法系統(tǒng)開銷較小,會發(fā)生Belady現(xiàn)象
- Clock算法是它們的折衷
- 對于未被訪問的頁面,Clock和LRU算法的表現(xiàn)一樣好
- 對于被訪問過的頁面,Clock算法不能記錄準確訪問順序,而LRU算法可以
進程
組成
- 程序代碼(文本段text )
- 當前活動(PC和CPU寄存器)
- 堆棧段(stack)(包含臨時數(shù)據(jù),如函數(shù)參數(shù)、返回地址和局部變量)
- 數(shù)據(jù)段(data)(包含全局變量)
- 堆(heap)(包含運行期間內存的動態(tài)分配)
特點:
- 動態(tài)性
可動態(tài)地創(chuàng)建、結束進程 - 并發(fā)性
進程可以被獨立調度并占用處理機運行 - 獨立性
不同進程的工作不相互影響 - 制約性
因訪問共享數(shù)據(jù)/資源或進程間同步而產生制約
進程 = 執(zhí)行中的程序 = 程序 + 執(zhí)行狀態(tài)
進程 = CPU + 內存

- 掛起(Suspend):把一個進程從內存轉到外存
線程:
優(yōu)點:
- 實體之間可以并發(fā)執(zhí)行
- 各個線程之間可以共享地址空間和文件等資源
缺點: - 一個線程崩潰,會導致其所屬進程的所有線程崩潰
- 進程: 資源分配單位
地址空間(代碼段、數(shù)據(jù)段)、打開的文件等各種資源 -
線程:處理機調度角色:指令流執(zhí)行狀態(tài)
image.png
- 進程是資源分配單位,線程是CPU調度單位
- 進程擁有一個完整的資源平臺,而線程
只獨享指令流執(zhí)行的必要資源,如寄存器和棧 - 線程具有
就緒、等待和運行三種基本狀態(tài)和狀態(tài)間的轉換關系 - 線程能減少并發(fā)執(zhí)行的時間和空間開銷
線程的三種實現(xiàn)方式
- 用戶線程:在用戶空間實現(xiàn)
- 內核線程:在內核中實現(xiàn)
- 輕量級進程:在內核中實現(xiàn),支持用戶線程
用戶線程
- 對操作系統(tǒng)內核透明
- 不需要變態(tài),速度快
- 實現(xiàn)靈活,每個線程都可以有自己的線程調度策略
- 實現(xiàn)復雜,容易一崩全崩,不支持搶占
- 按CPU分配給進程的時間再做分配,時間少
內核線程
輕量級進程

??內核支持的用戶線程。一個進程可有一個或多個輕量級進程,每個輕量級進程由一個單獨的內核線程來支持。
- 能夠做到由操作系統(tǒng)內核通過輕量級線程來調度線程,防止一個線程阻塞導致進程癱瘓。
- 用戶線程通過LWP訪問內核,內核通過LWP控制用戶線程。節(jié)省資源
- 支持大規(guī)模的UT(對于服務器這個至關重要)
