前段時間看了進程管理,覺得對編程簡直大有裨益,至少對于多線程編程方面,對系統的進程管理有了非常深刻的理解,看來還是要多學習。今天開始學習內存管理這一節,看了一遍沒怎么看懂,于是在這里寫下筆記,慢慢咀嚼,直到看明白。
- 從源程序變成在內存中執行的程序
- 編譯
將源代碼編譯成若干個目標模塊 - 鏈接
將目標模塊和需要的庫函數鏈接在一起,形成完成的裝入模塊 - 裝入
由裝入程序將裝入模塊裝入內存執行
- 程序鏈接三種方式
- 靜態鏈接
程序運行之前,將目標模塊和庫函數鏈接成完整的可執行程序 - 裝入時動態鏈接
在裝入內存的時候,邊裝入邊對目標模塊和庫函數進行鏈接 - 運行時候動態鏈接
在程序執行的時候需要該目標模塊的時候,才對其進行鏈接
- 程序裝入的時候的三種方式
- 絕對裝入
編譯程序產生的是絕對地址的目標代碼,絕對裝入程序按照絕對地址,將程序和數據裝入內存,程序的邏輯地址和實際內存的地址完全相同,所以不需要進行地址變換,只適用于單道程序環境。 - 可重定位裝入
多個目標模塊的起始地址都是從0開始,程序中其它地址都是相對于起始地址的,根據內存當前情況,將裝入模塊裝入到內存的適當位置,所以必須分配作業要求的全部內存空間。裝入的時候對目標程序的指令和數據的修改過程稱為重定位,地址變換是在裝入時候一次性完成的,因此稱為靜態重定位。 - 動態運行時裝入
裝入程序在把裝入模塊裝入內存后,不把相對地址轉換為絕對地址,直到程序真正執行的時候完成轉換,所以裝入內存后的所有地址均為相對地址,需要硬件重定位寄存器的支持。
邏輯地址空間
每個目標模塊都是從0開始編址,稱為目標模塊的相對地址也稱為邏輯地址,鏈接程序將依次將各個模塊相對地址構成統一的從0開始編址的邏輯地址空間,不同進程可以有相同的邏輯地址,因為這些地址在裝入內存的時候可以映射到主存的不同位置。物理地址空間
內存中物理單元的集合,地址轉換的最終地址,進程在運行的時候指令和數據都要通過物理地址從主存中存取。地址重定位就是將邏輯地址轉換成物理地址。內存保護
- CPU設置一對上,下限寄存器
存放用戶作業在主存的下限和上線地址,CPU要訪問一個地址的時候,分別與這兩個地址進行比較,判斷是否越界。 - 重定位寄存器(基址寄存器)和界地址寄存器(限長寄存器)
首先邏輯地址和界地址寄存器進行比較,如果沒有發生越界,加上重定位寄存器的值后映射成物理地址,送交內存單元。所以界地址寄存器含有邏輯地址的最大值。
覆蓋
將用戶空間分成一個固定區和幾個覆蓋區,程序中經常活躍的部分放在固定區,其余部分,將要訪問的段放入覆蓋區,其它段放在外存中,在需要調用前,系統將其掉入覆蓋區,替換覆蓋區原有的段。不在覆蓋區的段會常駐內存。交換
將處于等待狀態的程序從內存移到輔存,換出。把準備好競爭CPU運行的程序從輔存移到內存,換入。內存管理器的交換過程速度足夠快,總有進程在內存中可以執行。
交換技術在不同進程或者作業中進行,覆蓋用于同一個進程或者程序中。覆蓋技術要求給出程序段之間的覆蓋結構,對于主存無法存放用戶程序的矛盾,是通過虛擬內存技術來解決的。
連續分配管理方式
給用戶程序分配一個連續的內存空間。
這塊將是非常關鍵而且重要的部分了,涉及了單一連續分配,固定區分配和動態分區分配。
單一連續分配
內存分為系統區和用戶區,因為只有一道程序,所以無需內存保護,無外部碎片,可以采用覆蓋技術,只能用于單用戶單任務的操作系統,有內部碎片,存儲器利用率低。固定分區分配
將用戶內存空間分為多個固定大小的區域,每個分區只裝入一道作業,有空閑分區的時候再從外存的后備作業隊列中,選擇適當大小的作業裝入該分區。
- 分區大小相等
- 分區大小不等
便于內存分配,將分區按照大小排隊,建立一張分區說明表。回憶之。包含每個分區的起始地址,大小和狀態。
兩個問題,程序可能太大而放不進任何一個分區里,這時需要使用覆蓋技術來使用內存空間。內部碎片,當程序小于固定分區大小的時候,也占用了一個完整的內存分區空間。
- 動態分區分配
可變分區分配,動態劃分內存的分區方法,根據進程的大小動態建立分區,使得分區大小正好適合進程的需要。系統中的分區大小和數目是可以變化的。
在系統運行過程中,會產生較多的小的內存塊,稱為外部碎片。克服外部碎片可以通過緊湊技術解決,操作系統不時的對進程進行移動和整理,需要動態重定位寄存器的支持。
動態分區的分配策略,是指將內存中的空閑塊如何分配給進程使用:
- 首次適應算法
空閑分區按照地址遞增的順序,分配內存的時候按照順序查找,找到第一個能滿足要求的分區 - 最佳適應算法
空閑分區按照容量遞增排序,找到第一個能夠滿足要求的分區 - 最壞適應算法
空閑分區按照容量遞減排序,找到第一個能夠滿足要求的分區 - 鄰近適應算法
分配內存的時候從上次查找結束的位置開始繼續尋找,循環首次適應算法
首次適應算法會使得在內存的低地址處出現很多小的空閑分區(因為一般在內存低地址處分配空間),每次分配查找的時候,要經過這些分區,增加了查找的開銷。
鄰近適應算法會在內存的末尾分配空間,內存在前面使用后釋放,不會參與分配,然后分裂成小碎片,通常比首次適應算法的結果要差。
最佳適應算法以容量遞增的形式分配分區,會留下很小的難以利用的內存塊,因此會產生最多的外部碎片。
最壞適應算法以容量遞減的形式分配分區,會把最大的連續內存劃分開,會很快導致沒有可用的大的內存塊。
內部碎片:存在于固定分區中,分區內部有空間浪費,稱為內部碎片。
外部碎片:指在所有分區外的存儲空間會變成越來越多的碎片,存在于動態分區分配中,各個進程將內存區域分配后,內存區域會殘留的小的內存塊。
非連續分配管理方式
允許一個程序分散的裝入到不相鄰的內存分區中,需要額外的空間去存儲它們分散區域的索引,非連續分配方式的存儲密度小于連續存儲方式。
包括分頁存儲管理方式和分段存儲管理方式,其中分頁存儲管理方式分為基本分頁存儲管理方式和請求分頁存儲管理方式。
- 基本分頁存儲管理方式
把主存空間劃分為大小相等而且固定的比較小的塊,作為主存的基本單位,每個進程也以塊為單位進行劃分,進程在執行的時候,以塊為單位逐個申請主存中的塊空間。
這樣的分配方法不會產生外部碎片,進程只會為最后一個不完整的塊申請一個主存塊空間的時候,產生主存碎片,不過這個碎片相對于進程來講也是非常小的,每個進程平均產生半個塊大小的內部碎片,頁內碎片。- 頁面
進程的塊稱之為頁。
內存中的塊稱之為頁框,也稱為頁幀。
外存中也以同樣的單位進行劃分,稱為塊。
進程在執行時候需要申請主存空間,就是為每個頁面分配主存中可用的頁框,所以頁和頁框一一對應。
頁面大小就是說進程分成的基本單位頁的大小,應該是2的整數冪。頁面大小適中,太小會導致頁面數過多,頁表就太長,占用大量內存,增加硬件地址轉換的開銷,降低頁面換入/換出效率。頁面過大導致頁內碎片增大,降低內存的利用率。 - 地址結構
前一部分為頁號12-31位,所以地址空間最多有2^20頁,后一部分是頁內偏移量W,12位,0-11位,所以每頁大小為4KB。地址結構決定了虛擬內存的尋址空間有多大。
其實整個頁面就是地址的集合,所以頁面便移量也就確定了一定位置的物理地址。從而確定了從邏輯地址轉換到物理地址的一個位置。
- 頁面
- 頁表
在內存中找到進程的每個頁面所對應的物理塊,系統為每個進程建立了一個頁表。記錄頁面在內存中對應的物理塊號,頁面存放在內存中。
頁表由頁表項組成,頁表項第一部分是進程的頁號,第二部分是物理內存中的塊號,該塊號和地址的第二部分頁內偏移量共同組成物理地址。
頁表的作用是實現從頁號到物理塊號的地址映射。
- 基本地址變換機構
頁表長度指的是一共有多少頁M。
頁表項長度指的是每一頁表項占多大的內存空間。
頁面大小是指每一頁占多大的內存空間L。
所以地址變換機構將邏輯地址轉換成內存的物理地址的一般步驟如下:
- 從邏輯地址A計算頁號P和頁內偏移量,P=A/L,W=A%L。L是頁面大小。
- 比較頁號P和頁表長度M,P>=M,則產生越界中斷,否則繼續執行。
- 計算對應頁號的頁表項地址,從該頁表項中提取物理塊號。對應的頁表項地址=P*頁表項長度+F(頁表起始地址F),索引到該頁表項后,取得物理塊號b
- 計算出內存中物理地址E=b*L+W,因為進程中的頁面和內存中的頁面大小都是一致的,一一對應。所以通過物理塊號乘以頁面大小,加上頁面便移量就可以找到對應的物理地址。
頁式管理只要給出一個整數就能確定對應的物理地址,因為頁面大小L是固定的,頁式管理中地址空間是一維的。 - 頁表項大小的確定
頁表項是為了找到相應頁在內存中的位置。32位的邏輯地址空間(4GB),一頁4KB,那么地址空間內一共可以有1M頁面,所以至少需要20位來表示所有頁面,所以頁表項大小至少有3B(20/8),為了保證頁表項能夠指向所有頁面,頁表項的大小應該大于3B,當然可以選擇更大的頁表項讓一個頁面正好容下整個頁表項以方便存儲,如果是4B,那么一頁存儲1024個頁表項。一個頁表是由頁表項組成的,但是有多少頁表項是由有多少頁面來決定的,多少頁面又是由多少進程來決定的。
- 具有快表的地址變換機構
如果頁表全部放在內存中,則存取一個數據或一條指令需要訪問兩次內存:第一次試訪問頁表,找到物理地址,然后通過物理地址存取數據和指令。
在地址變換機構中增設了一個具有并行查找能力的高速緩沖存儲器-快表,又稱為聯想寄存器TLB,用來存放當前訪問的若干頁表項,加速地址變換的過程,主存中頁表稱為慢表。
具有快表的分頁機制中,地址的變換過程:
- CPU給出邏輯地址后,由硬件進行地址轉換將頁號送入高速緩存寄存器中,將頁號和快表中的所有頁號進行比較。
- 如果找到匹配的頁號,那么直接從中取出該頁對應的頁框號,也就是物理塊號,算出物理地址,存取數據僅需要訪問一次主存。
- 沒有找到,那么訪問主存中的頁表,讀出頁表項后放入快表,快表滿了的話,按照一定的算法對舊的頁表進行替換。
- 兩級頁表
- 對頁表以及相應過程的進一步理解
頁面就是將進程以塊為單位進行劃分,所以比如40M的進程,頁表項就是40MB/4KB*4B,4KB是頁面大小,也就是每一塊的大小,所以需要1萬個頁面,乘以4B頁表項大小,也就是頁表的大小。如果將所有的頁表項內容保存在內存中,需要10個內存頁框來保存整個頁表,因為每個頁面框可以保存1024個頁表項,4KB/4B。
頁框也是將主存進行同樣的劃分,所以對于32位的邏輯地址空間,頁面大小4KB,頁表項4B,實現進程對整個邏輯地址空間進行映射,則每個進程需要2^20,100萬個頁表項,所以每個進程僅頁表這一項就要4MB的主存空間,并且需要100萬*4B/4KB=1024頁,也就是說頁表需要1024頁才能存儲完。
但是實際執行的時候只需要幾十個頁面進入內存頁框就可以運行,但是如果要將10個頁面的頁表都放入內存,卻只用幾十個頁面,不到一個頁面的頁表,這樣就極大的降低了內存利用率。并且大部分情況下,映射需要的頁表項都在頁表的同一個頁面中。
使用層次結構的頁表:將頁表的10頁空間也進行地址映射,建立上一級頁表,存儲頁表的映射關系,10個頁面進行映射只需要10個頁表項,而上一級頁表僅僅需要1頁就足夠了,1頁可以存儲1024個頁表項。
所以需要一張索引表來尋找對應的表,并且不用把所有的頁表都調入內存,只有需要的時候才調入。構造一個頁表的頁表,就是二級頁表。頂級頁表最多只能由1個頁面,也就是1024個頁表項,對應1024個頁面,占用的地址位數是10位,log2(1024)=10
所以對于一個32位的邏輯地址空間,32-10-12(頁內偏移地址)=10位,所以二級頁表大小也在一頁之內。
所以假設第一級頁表有10個頁表項,則說明頁表有10個頁面,如果第一級頁表有1024個頁表項,說明頁表有1024個頁面,也就是32位邏輯空間最大的頁表項了。然后第一級頁表的頁表項分別索引第二級頁表,假設第一個頁表項下的第二級頁表,這就是說明索引了原來第一個頁表頁面的所有頁表項。所以10個頁面的頁表恰好被整個二級頁表索引完全。第一級頁表大小在一頁之內,第二級頁表大小也在一頁之內。
換一種說法就是第一級頁表的頁表項表示你想索引哪一個頁面的頁表,第二級頁表的頁表項就是表明你想索引的頁面的頁表的所有能索引到物理塊的頁表項都在這里了。
- 基本分段存儲管理方式
分段管理方式是考慮用戶和程序員,以滿足方便編程,信息保護和共享,動態增長及動態鏈接等多方面的需要。
- 分段
段式管理方式按照用戶進程中的自然段劃分邏輯空間,段內要求連續,段間不要求連續,整個作業的地址空間是二維的,這里的意思指的是一個進程可以分為好幾個段的邏輯地址。
邏輯地址由段號S和段內偏移量W兩部分組成,S有16位,因此一個作業最多有65536個段,W有16位,最大段長為64KB。
段式系統中,段號和段內偏移量必須由用戶顯示提供,高級程序設計語言中,工作由編譯程序完成。 - 段表
每一個段表項對應進程的一個段,段表項記錄段號,段長以及段在內存中的起始地址。執行中的進程可以通過查找段表,找到每個段對應的內存區。段表用于實現從邏輯段到物理內存區的映射。 - 地址變換機構
段表寄存器:用于存放段表起始地址F和段表長度M。- 從邏輯地址A取出前幾位是段號S,后幾位是段內偏移量W,段式管理一般以二進制給出邏輯地址。
- 比較段號S和段表長度M,如果S>=M,產生越界中斷,否則繼續執行。
- 求出段號S對應的段表項的地址=段表起始地址F+段號S*段表項長度,然后取出段長C,如果段內偏移量>=C,產生越界中斷,否則繼續執行,取出段在內存的起始地址b,從這里可以看出其實段表只有兩項,就是段長和段在內存中的起始地址。段號其實可以省略。
- 計算物理內存地址E=b+W
- 段的共享和保護
段的共享是通過兩個作業的段表中相應表項指向被共享的段的同一個物理副本來實現的,純代碼或者可重入代碼和不能修改的數據是可以共享的,可修改的代碼和數據不能共享。
分段管理的保護由兩種:- 存取控制保護
- 地址越界保護
段表寄存器中段表長度和邏輯地址中的段號進行比較。
另外一個是段表項中的段長和邏輯地址中的段內位移進行比較。
段號和段內偏移一定要顯示給出,因此分段管理的地址空間是二維的。
- 段頁式管理方式
作業的地址空間首先被分成了若干個邏輯段,每段都有自己的段號,然后將每一段分成若干個大小固定的頁,對內存空間的管理和分頁存儲管理一樣,將其分為若干個和頁面大小相同的存儲塊,對內存的分配以存儲塊為單位。
- 地址變換
每個進程一個段表,每個分段一張頁表,段表表項中至少包括段號,頁表長度和頁表起始地址,頁表表項中至少包括頁號和塊號。
系統中還有段表寄存器,作業的段表起始地址和段表長度,還有一個頁表寄存器。作用有兩個,一是段表或者頁表中尋址,二是判斷是否越界。在一個進程中,段表只有一個,頁表有多個。
地址變換,通過段表查到頁表起始地址,通過頁表找到頁幀號,最后形成物理地址。一次訪問要訪問三次主存,可以添加快表來加快查找速度,關鍵字由段號,頁號組成,值是對應的頁幀號和保護碼。
段頁式管理的地址空間是二維的。