1、前言程序員
在分析了處理器調度後,接着分析存儲器管理,如何對存儲器進行有效的管理,直接影響着存儲器的利用率和系統性能。下面,開始存儲器管理的學習。算法
2、存儲器的層次結構編程
2.1 主存儲器緩存
主存儲器是計算機系統中的一個主要部件,用於保存進程運行時的程序和數據,CPU的控制部件只能從主存儲器中取得指令和數據,數據可以從主存儲器中讀取並將他們裝入到寄存器中,或者從寄存器存入到主存儲器,CPU與外圍設備交換的信息通常也依託於主存儲器地址空間。可是,主存儲器的訪問速度遠低於CPU執行指令的速度,因而引入了寄存機和告訴緩衝。數據結構
2.2 寄存器併發
寄存器訪問速度最快,能與CPU協調工做,價格昂貴,容量不大,寄存器用於加速存儲器的訪問速度,如用寄存器存放操做數,或用做地址寄存器加快地址轉換速度等。函數
2.3 高速緩存性能
高速緩存容量大於或遠大於寄存器,但小於內存,訪問速度高於主內存器,根據程序局部性原理,將主存中一些常常訪問的信息存放在高速緩存中,減小訪問主存儲器的次數,可大幅度提升程序執行速度。一般,進程的程序和數據存放在主存,每當使用時,被臨時複製到高速緩存中,當CPU訪問一組特定信息時,首先檢查它是否在高速緩存中,若是已存在,則直接取出使用,不然,從主存中讀取信息。有的計算機系統設置了兩級或多級高速緩存,一級緩存速度最高,容量小,二級緩存容量稍大,速度稍慢。學習
2.4 磁盤緩存ui
磁盤的IO速度遠低於對主存的訪問速度,所以將頻繁使用的一部分磁盤數據和信息暫時存放在磁盤緩存中,可減小訪問磁盤的次數,磁盤緩存自己並非一種實際存在的存儲介質,它依託於固定磁盤,提供對主存儲器空間的擴充,即利用主存中的存儲空間,來暫存從磁盤中讀出或寫入的信息,主存能夠看作是輔存的高速緩存,由於,輔存中的數據必須複製到主存方能使用,反之,數據也必須先存在主存中,才能輸出到輔存。
3、程序的裝入和連接
爲了使程序可以運行,必須先爲之建立進程,而建立進程的第一件事,就是將程序和數據裝入內存,如何將一個用戶源程序變爲一個可在內存中執行的程序,一般要通過以下幾步,首先是編譯(由編譯程序將用戶源代碼編譯成若干個目標模塊),其次是連接(由連接程序將編譯後造成的一組目標模塊,以及它們所須要的庫函數連接在一塊兒,造成一個完整的裝入模塊),最後是裝入(由裝入程序將裝入模塊裝入內存)。
3.1 程序的裝入
在裝入一個模塊到內存時,有絕對裝入方式,可重定位裝入方式,動態運行時裝入方式。
① 絕對裝入方式,若是在編譯時知道程序駐留在內存的什麼位置,那麼,編譯程序將產生絕對地址的目標代碼,絕對裝入方式按照裝入模塊中的地址,將程序和數據裝入內存,裝入模塊被裝入內存後,因爲程序中的邏輯地址與實際內存地址徹底相同,故不須要對程序和數據的地址進行修改。
② 可重定位裝入方式,因爲絕對裝入方式只能將目標模塊裝入到內存中事先指定的位置,在多道程序環境下,編譯程序不可能事先知道所編譯的目標模塊應放在內存的何處,所以,絕對裝入方式只適用於單道程序環境,在多道程序環境下,所獲得的目標模塊的起始地址一般都是以0開始的,程序中的其餘地址也都是相對於起始地址計算的,此時應採用可重定位裝入方式,根據內存的當前狀況,將裝入模塊裝入到內存的適當位置。該方式會使裝入模塊中的全部邏輯地址與實際裝入內存的物理地址不一樣,須要對數據地址和指令地址進行修改,一般把再裝入時對目標程序中指令和數據的修改過程稱爲重定位,又由於地址變換一般是在裝入時一次完成的,之後再也不變化,故稱爲靜態重定位。
③ 動態運行時裝入方式,可重定位裝入方式容許將裝入模塊裝入到內存中任何容許的位置,故可用多道程序環境,但這種方式並不容許程序運行時在內存中移動位置,由於,程序在內存中的移動,意味着它的物理位置發生了變化,這就必須對程序和數據的地址進行修改後方能運行。然而,在運行過程當中它在內存中的位置可能常常要改變,此時就應該採用動態運行時裝入方式。動態運行時的裝入程序在把裝入程序裝入內存後,並不當即把裝入模塊中的相對地址轉換爲絕對地址,而是把這種地址轉換推遲到程序真正要執行時才進行。所以,裝入內存後的全部地址都還是相對地址,爲了使地址轉換不影響指令的執行速度,須要重定位寄存器的支持。
3.2 程序的連接
源程序通過編譯後,可獲得一組目標模塊,再利用連接程序把這組目標模塊連接,造成裝入模塊,根據連接時間的不一樣,可把連接分爲靜態連接(在程序運行以前,先將各目標模塊及他們所需的庫函數,連接成一個完整的裝配模塊,之後再也不拆開)、裝入時動態連接(將用戶源程序編譯後所獲得的一組目標模塊,在裝入內存時,採用邊裝入邊連接的連接方式)、運行時動態連接(對某些目標模塊的連接,是在程序執行中須要蓋模塊時,纔對它進行連接)。
① 靜態連接,在將目標模塊裝配成一個裝入模塊時,須要對相對地址進行修改(因爲編譯程序產生的全部目標模塊中,使用的都是相對地址,其起始地址都爲0,每一個模塊中的地址都是相對於起始地址計算的)。也須要變換外部調用符號(將每一個模塊中所用的外部調用符號都變換爲相對地址),這種先進行連接所造成的一個完整的裝入模塊,又稱爲可執行文件,一般都再也不拆開它,要運行時可直接將它裝入內存,這種事先進行連接,之後再也不拆開的連接方式,稱爲靜態連接方式。
② 裝入時動態連接,用戶源程序經編譯後所得是目標模塊,是在裝入內存時邊裝入邊連接的,即在裝入一個目標模塊時,若發生一個外部模塊調用事件,將引發裝入程序去找出相應的外部目標模塊,並將它裝入內存,裝入時動態連接有以下優勢,便於修改和更新(各目標模塊是分開的存放的,因此要修改或更新各目標模塊很是容易),便於實現對目標模塊的共享(很容易將一個目標模塊連接到幾個應用模塊上,實現多個應用程序對該模塊的共享)
③ 運行時動態連接,將某些模塊的連接推遲到程序執行時才進行連接,即在執行過程當中,當發現一個被調用模塊還沒有裝入內存時,當即由OS去找到該模塊並將之裝入內存,把它連接到調用者模塊上,凡在執行過程當中未被調用到的模塊,都不會被調入內存和被連接到裝入模塊上,這樣不只加快程序的裝入過程,同時也節省了大量的內存空間。
4、連續分配方式
連續分配方式是指爲一個用戶程序分配一個連續的內存空間,能夠將連續分配方式分爲單一連續分配、固定分區分配、動態分區分配、動態重定位分區分配。
4.1 單一連續分配
這是一種最簡單的存儲管理方式,但只能在單用戶、單任務的操做系統中,將內存分爲系統區和用戶區,系統區供OS使用,一般放在內存的低地址,用戶區是指除系統區之外的所有內存空間,提供給用戶使用。
4.2 固定分區分配
固定分區分配是一種最簡單的可運行多道程序的存儲管理方式,將內存用戶空間劃分爲若干個固定大小的區域,在每一個分區只裝入一道做業,這樣,便容許多道做業併發執行,當有空閒分區時,即可以再從外存的後備做業隊列中選擇一個適當大小的做業裝入該分區,當該做業結束時,又可再從後備做業隊列中找出另外一做業調入該分區。
對於內存的用戶空間的劃分,有以下兩種方法。
① 分區大小相等,即全部的內存分區大小相等。缺點是缺少靈活性,即當程序過小時,會形成內存資源的浪費,程序太大時,一個分區由不足以裝入該程序,只是該程序沒法運行。
② 分區大小不等,把內存區劃分紅含有多個較小的分區、適量中等分配和少許大分區,這樣,即可根據程序的大小爲之分配適當的分區。
爲了便於內存分配,將分區按大小進行排隊,併爲之簡歷一張分區使用表,其中各表項包括每一個分區的起始地址、大小、狀態(是否已分配),當有一個程序須要裝入時,由內存分配程序檢索該表,從中找出一個能知足要求的,還沒有分配的分區,將之分配給該程序,而後將該表項中的狀態設置爲已分配,若未找到大小足夠的分區,則拒絕爲該用戶分配內存。
4.3 動態分區分配
動態分區分配是根據進程的實際須要,動態地爲之分配內存空間,在實現可變分區分配時,將涉及到分區分配中所用的數據結構、分區分配算法、分區的分配和回收等。
① 分區分配中的數據結構,爲了實現分區分配,胸中必須配置相應的數據結構,用來描述空閒分區和已分配分區的狀況,爲分配提供依據,經常使用的數據結構有以下兩種形式:空閒分區表(在系統中設置一張空閒分區表,用於記錄每一個空閒分區的狀況,每一個空閒分區佔一個表目,表目中包括分區序號、分區始址、分區大小等,在前面已有介紹)、空閒分區鏈(爲了實現對空閒分區的分配和連接,在每一個分區的起始部分,設置一些用於控制分區分配的信息,以及用於連接各分區所用的向前指針;在分區尾部設置一貫後指針,這樣,能夠將空閒分區連接成一個雙向鏈),爲了檢索方便,在分區尾部重複設置狀態爲和分區大小表目,當分區被分配出去之後,把狀態爲從0改爲1,此時先後指針都失去意義(已經再也不空閒鏈表中)。
② 分區分配算法,爲把一個新做業裝入內存,需按照必定的分配算法,從空閒分區表或空閒分區鏈中選出一分區分配給該做業,目前經常使用一下五種分配算法
1. 首次適應算法(First Fit)
以空閒分區鏈爲例進行說明,FF算法要求空閒分區鏈以地址遞增的次序連接,在分配內存時,從鏈首開始順序查找,直至找到一個大小能知足要求的空閒分區爲止,而後再按照做業的大小,從該分區劃出一塊內存空間分配給請求者,餘下的空閒分區仍留在空閒鏈中,若從鏈首直至鏈尾都不能找到一個能知足要求的分區,則這次內存分配失敗,返回。該算法傾向於優先利用內存中低址部分的空閒分區,從而保留了高址部分的大空閒區,這給之後達到的大做業分配大的內存空閒創造了條件,缺點在與低地址空間不斷被劃分,會留下許多難以利用的、很小的空閒分區,而每次查找又都是從低地址部分開始,這無疑會增長查找可用空閒分區的開銷。
2. 循環首次適應算法(Next Fit)
由首次適應算法演變而來,在未進程分配內存空間時,再也不是每次都從鏈首開始查找,而是從上次找到的空閒分區的下一個空閒分區開始查找,直至找到一個能知足要求的空閒分區,從中劃分出一塊與請求大小相等的內存空間分配給做業。進行空閒分區分配時,會採用循環查找方式,即若是最後一個(鏈尾)空閒分區的大小仍不能知足要求,則返回第一個空閒分區。該算法能使內存中的空閒分區分佈得更加均勻,從而減小了查找空閒分區時的開銷,可是會缺少大的空閒分區。
3. 最佳適應算法(Best Fit)
該算法老是能把知足要求、又是最小的康縣分區分配給做業,避免大材小用,爲了加速尋找,該算法要求把全部的空閒分區按其容量以從小到大的順序造成一個空閒分區鏈,這樣,第一次就能找到知足要求的空閒區,必然是最佳的,孤立地看,最佳適應算法彷佛是最佳的,然而宏觀上卻不必定,由於每次分配後所切割下來的剩餘部分老是最小的,會留下不少難以使用的小空閒區。
4. 快速適應算法(Quick Fit)
該算法又稱爲分類搜索法,是將空閒分區容量大小進行分類,對於每一類具備相同容量的全部空閒分區,單獨設立一個空閒分區鏈表,這些,系統中存在多個空閒分區鏈表,同時在內存中設立一張管理索引表,該表的每一項對應了一種空閒分區類型,並記錄了該類型空閒分區鏈表表頭的指針。該算法的優勢是查找效率高,僅需根據進程的長度,尋找到能容納它的最小空閒區鏈表,並取下第一塊進行分配便可。該算法在進行空閒分區分配時,不會對任何分區產生分割,因此能保留大的分區,知足對大空間的需求,也不會產生內存碎片。可是在分區歸還主存時算法複雜,系統開銷大。
③ 分區分配操做,在動態分區分配存儲管理中,主要的操做是分配內存和回收內存。
1. 分配內存
系統利用某種分配算法,從空閒分區鏈(表)中找到所需大小的分區,其流程圖以下
說明:size表示事先規定的再也不切割的剩餘分區的大小。空閒分區表示爲m.size,請求分區的大小爲u.size。
2. 回收內存
當進程運行完畢釋放內存時,系統根據回收區的首址,從空閒區鏈(表)中找到相應的插入點,此時會出現以下四種狀況之一:回收分區與插入點的前一個空閒區F1相鄰接,此時將回收區與插入點的前一分區合併,沒必要爲回收區分配新表項,只須要修改前一分區F1的大小。回收分區與插入點的後以空閒分區F2相鄰接,此時將兩分區合併,造成新的空閒分區,用回收區的首址做爲新空閒區的首址,大小爲二者之和。回收區同時與插入點的前、後兩個分區鄰接,此時將三個分區合併,使用F1的表項和F1的首址,取消F2的表項,大小爲三者之和。回收區既不與F1鄰接,也不與F2鄰接,這時爲回收區單獨創建一個新表項,填寫回收區的首址和大小,並根據其首址插入到空閒鏈中的適當位置。
4.4 夥伴系統
夥伴系統規定,不管已分配分區仍是空閒分區,其大小均爲2的k次冪,k爲整數,1<= k <= m,其中,2^1表示分配的最小分區的大小,2^m表示分配的最大分區的大小,一般2^m是整個可分配內存的大小。假設系統開始時的初始容量爲2^m個字,因爲不斷切分,可能會造成若干個不連續的空閒分區,將這些空閒分區根據分區的大小進行分類,對於每一類具備相同大小的全部空閒分區,單獨設立一個空閒分區雙向鏈表。這樣,不一樣大小的空閒分區造成了k個空閒分區鏈表。
當須要爲進程分配一個長度爲n的存儲空間時,首先計算一個i值,使2^i-1 < n <= 2^i,而後,在空閒分區大小爲2^i的空閒分區鏈表中查找,若找到,即把該空閒分區分配給進程,不然,代表2^i的空閒分區已經耗盡,在大小爲2^i+1的空閒分區鏈表中查找,若存在,則將該空閒分區分爲兩個大小爲2^i的分區,一個用於分配,一個加入到大小爲2^i的空閒分區鏈表中,若仍是不存在,則繼續在大小爲2^i+2的空閒分區鏈表中查找,若存在,則將空閒分區進行兩次分割,一次分割爲兩個大小爲2^i+1的空閒分區,一個加入到大小爲2^i+1的空閒分區鏈表中,另一個繼續進行分割,分紅兩個大小2^i的空閒塊,一個用於分配,另一個加入到大小爲2^i的空閒分區鏈表中,以此類推。在最壞的狀況下,可能須要對2^k的空閒分區進行k此分割才能獲得所需分區。
當回收空閒分區時,也須要通過屢次合併,如回收大小爲2^i的空閒分區時,若事先已經存在2^i的空閒分區,則應將其與夥伴分區合併爲一個大小爲2^i+1的空閒分區,若事先已存在2^i+1的空閒分區,則再次進行合併,合併爲2^i+2的分區,以此類推。
4.5 可重定位分區分配
在連續分配方式中,必須把一個系統或用戶程序裝入一連續的內存空間,若果在系統中只有若干個小的分區,即便他們容量總和大於要裝入的程序,但因爲這些分區不相鄰接,也沒法把該程序裝入內存。若想裝入,則將內存中的全部做業進行移動,使他們所有相鄰接,這樣,便可把原來分散的多個小分區拼接成一個大分區,這時,就能夠把做業裝入該區。通過緊湊後的某些用戶程序在內存中的位置發生了變化,此時若不對程序和數據的地址加以修改(變換),則程序必將沒法執行,爲此,在每次緊湊以後,都必須對移動了的數據和程序進行重定向。
在動態運行時裝入的方式中,做業裝入內存後的全部地址都仍然是相對地址,將相對地址轉化爲物理地址的工做,退推遲到程序指令要真正執行時進行。爲了是地址變換不影響指令的執行速度,在系統中增設了一個重定位寄存器,用它來存放程序(數據)在內存中的起始地址。在程序執行時,真正訪問的內存地址是相對地址與重定位寄存器中的地址相加而造成的。該動做是隨着對每條指令或數據的訪問自動進行的,故稱爲動態重定位,當系統對內存進行了緊湊而使若干程序在內存中移動時,不須要對程序作任何修改,只要用該程序在內存的新起始地址去置換原來的起始地址便可。
動態重定位分區分配算法與動態分區分配算法基本上相同,差異僅在於:在這種分配算法中,增長了緊湊功能,一般,在找不到足夠大的空閒分區來知足用戶需求時進行緊湊。
4.6 對換
在多道程序環境下,一方面,在內存中的某些進程因爲某事件還沒有發生而被阻塞運行,但它卻佔用了大量的內存空間,甚至有時可能出如今內存中全部進程都被阻塞而迫使CPU中止下來等待的狀況,另外一方面,卻有不少做業在外存上等待,因無內存而沒法進入內存運行的狀況,這是對系統資源的浪費,爲了解決這個問題,增設了對換設施,對換是把內存中暫時不能運行的進程或者暫時不用的程序和數據調出到外存上,以便騰出足夠的內存空間,再把已具有運行條件的進程或者進程所須要的程序和數據調入內存。對換是提升內存利用率的有效措施。若是對換的單位是進程,便稱爲總體對換或進程對換,爲了實現進程對換,系統必須實現對換空間的管理、進程的換出、進程的換入。
① 對換空間的管理,在具備對換功能的OS中,一般把外存分爲文件區和對換區,前者用於存放文件,後者用於存放從內存換出的進程。因爲文件一般是較長久的駐留在外存上,文件區的管理主要目標是提升存儲空間的利用率,採起離散分配方式,進程一般在對換區中駐留的時間較短暫,對換操做較頻繁,故對對換空間管理的主要目標是提升進程換入和換出的速度,採起的是連續分配的方式,較少考慮外存中的碎片問題。
② 進程的換出,每當進程因爲建立子進程而須要更多的內存空間,但又無足夠的內存空間狀況時,系統應將某進程換出,首先,系統首先選擇處於阻塞狀態且優先級最低的進程做爲換出進程,而後啓動磁盤,將該進程的程序和數據傳送到磁盤的對換區上,若傳送過程沒有錯誤,則可回收該進程所佔用的內存空間,並對該進程的進程控制塊作相應的修改。
③ 進程的換入,系統定時地查看全部進程的狀態,從中找出就緒狀態但已換出的進程,將其中換出時間最久的進程做爲換入進程,將其換入,直至無換入的進程或無可換出的進程爲止。
5、基本分頁存儲管理方式
連續分配方式會造成不少碎片,爲之進行緊湊操做的開銷很是大,若是容許一個進程直接分散地裝入到許多不相鄰接的分區中,則無須進行緊湊操做,基於這一思想產生了離散分配方式,若是離散分配的基本單位是頁,則稱爲分頁存儲管理方式,若爲段,則爲分段存儲管理方式。
5.1 頁面與頁表
分頁存儲管理是將一個進程的邏輯地址空間分紅若干個大小相等的片,稱爲頁面或頁,併爲各頁進行編號,從0開始。相應地,把內存空間分紅與頁面相同大小的若干個存儲塊,稱爲(物理)塊或者頁框,也一樣爲它們編號,如0#塊,1#塊等。在未進程分配內存時,以塊爲單位將進程的若干個頁分別裝入到多個能夠不相鄰接的物理塊中,因爲進程的最後一頁常常裝不滿一塊而造成不可利用的碎片,稱之爲頁內碎片。
在分頁系統中的頁面其大小應適中,頁面若太大,一方面能夠是內存碎片減小,有利於提供內存利用率,可是,每個進程佔用的頁面較多,致使頁表過長,佔用太多內存,會下降頁面換進換出的效率。頁面若太大,可減小頁表的長度,提供頁面換進換出的速度,可是,內存碎片會增大,因此,也頁面大小應適中,一般爲512B~8K
分頁地址中的地址結構以下
說明:前一部分爲頁號P,後一部分爲位移量W(或稱爲頁內地址),總共32位,其中0~11位爲頁內地址,每頁大小4KB,12~31位爲頁號,地址空間最多容許1M頁。
爲了可以保證在內存中找到每一個頁面所對應的物理塊,系統爲每一個進程創建了一張頁面映射表,簡稱爲頁表。頁表項紀錄了相應頁在內存中對應的物理塊號,在配置了頁表後,進程執行時,經過查找該表,便可找到每頁在內存中的物理塊號,頁表實現了從頁號到物理塊號的地址映像。
即便在簡單的分頁系統中,也常在頁表的表項中設置一存取控制字段,用於對該存儲塊中的內存加以保護,當存取控制字段僅有一位時,可用來規定該存儲塊中的內存時容許讀/寫,仍是隻讀;若存取控制字段爲二位,則可規定爲讀/寫、只讀、只執行等存取方式。
5.2 地址變換機構
爲了可以將用戶地址空間中的邏輯地址變換爲內存空間中的物理地址,在系統中必須設置地址變換機構,該機構的基本任務是實現從邏輯地址到物理地址的轉換,因爲頁內地址與物裏塊內的地址一一對應,無須再進行轉換,所以,地址變換機構的任務實際上只是將邏輯地址中的頁號轉換爲內存中的物理塊號。又由於頁面映射表的的做用就是用於實現從頁號到物理塊號的變換,所以,地址變換任務是藉助頁表來完成的。
頁表的功能能夠由一組專門的寄存器來實現,一個頁表項用一個寄存器,因爲寄存器具備較高的訪問速度,於是有利於提升地址變換的速度,但成本較高,且頁表項通常會不少,都使用寄存器實現不太現實,所以,頁表大多駐留在內存。在系統中只設置一個頁表寄存器PTR(Page-Table Register),用於存放頁表在內存的始址和頁表的長度,平時,進程執行時,頁表的始址和頁表長度存放在本進程的PCB中,當調度程序調度到某進程時,將這兩個數據裝入頁表寄存器,所以,在單處理機環境下,雖然系統中能夠運行多個進程,但只須要一個頁表寄存器。
當進程要訪問某個邏輯地址中的數據時,分頁地址變換機構會自動地將有效地址(相對地址)分爲頁號和頁內地址兩部分,再以頁號爲索引去檢索頁表,查找操做由硬件執行,在執行檢索前,先將頁號與頁表長度進行比較,若頁號大於或等於頁表長度,則表示本次訪問的地址超越了進程的地址空間,這一錯誤將被系統發現併產生一個地址越界中斷。若未出現錯誤,則將頁表始址加上頁號與頁表項長度的乘積,便獲得該表項在頁表中的位置,因而可從中獲得該頁的物理塊號,將之裝入物理地址寄存器,與此同時,再將有效地址寄存器中的頁內地址送入物理地址寄存器的塊內地址字段中,這樣,便完成了邏輯地址到物理地址的轉換。
上述操做中,每次存取一個數據時,都會訪問內存兩次,第一次是訪問內存中的頁表,從中找到指定頁的物理塊號,再將塊號與頁內偏移量W拼接,以造成物理地址,第二次訪問時,纔是從第一次所得的地址中得到所需數據,所以,這種方式會使計算機的處理速度下降一半,爲了提升地址變換速度,能夠在地址變換機構中增設一個具備並行查詢能力的特殊高速緩衝寄存器,又稱爲聯想寄存器或快表,用以存放當前訪問的那些頁表項。
此時的變換過程以下,在CPU給出有效地址後(邏輯地址),由地址變換機構自動的將頁號P送入高速緩衝寄存器,並將此頁號與高速緩存中的全部頁號進行比較,若其中有與之相匹配的頁號,便表示所要訪問的頁表項在快表中,因而,能夠直接從快表中讀出該頁所對應的物理塊號,並送到物理地址寄存器中,如在快表中沒有找到,則還須要再訪問內存中的頁表,找到後,把從頁表項讀出的物理塊好送入地址寄存器,同時,再將此頁表項存入快表的寄一個寄存器單元,即修改快表,若是快表已滿,則OS須要找到一個老的且已被認爲再也不須要的頁表項,將它換出。
5.3 兩級和多級頁表
現代計算機系統中,能夠支持很是大的邏輯地址空間(2^32~2^64),這樣,頁表就變得很是大,要佔用很是大的內存空間,如,具備32位邏輯地址空間的分頁系統,規定頁面大小爲4KB,則在每一個進程頁表中的頁表項可達1M(2^20)個,又由於每一個頁表項佔用一個字節,故每一個進程僅僅頁表就要佔用1MB的內存空間,並且要求連續,這顯然是不現實的,能夠經過以下兩個方法解決該問題。
① 採用離散分配方式來解決難以找到一塊連續的大內存空間的問題。
② 只將當前須要的部分頁表項調入內存,其他頁表項仍駐留在磁盤上,須要時再調入。
對於要求連續的內存空間來存放頁表的問題,可利用將頁表進行分頁,並離散地將各個頁面分別存放在不一樣的物理塊中的辦法來解決,一樣的,也要爲離散分配在頁表再創建一張頁表,稱爲外層頁表。在每一個頁表項中記錄了頁表頁面的物理塊號,以32位邏輯地址空間爲例進行說明。
說明:外層頁號P1爲10位,能夠表示1024個物理塊,外層頁表中的外層也內地址P2爲10位,能夠表示1024個物理塊,頁內地址爲12位,表示頁面大小爲4K。
說明:在頁表的每個表項中存放的是進程的某頁在內存中的物理塊號,如第0頁的0頁存放1#物理塊,第1頁存放4#物理塊,而在外層頁表的每一個頁表項中,所存放的是某頁表分頁的首址,如第0頁頁表存放在1011#物理塊中,第1頁頁表存放在1078#物理塊中。
爲了實現地址變換,在地址變換機構中須要增設一個外層頁表寄存器,用於存放外層頁表的始址,並利用邏輯地址中的外層頁號,做爲外層頁表的索引,從中找到指定頁表分頁的始址,在利用P2做爲指定頁表分頁的索引,找到指定的頁表項,其中即含有該頁在內存的物理塊號,用該塊號和頁內地址d便可構成訪問的內存物理地址。
將頁表施行離散分配的方法,雖然解決了對大頁表無需大片存儲空間的問題,可是並未解決用較少的內存空間去存放大頁表的問題,換言之,只用離散分配空間的辦法並未減小頁表所佔用的內存空間,解決辦法是把當前須要的一批頁表項調入內存,之後再根據須要陸續調入。在採用兩級頁表結構的狀況下,對於正在運行的進程,必須將其外層頁表調入內存,而對頁表則只須要調入一頁或者幾頁,爲了表徵某頁的頁表是否已經調入內存,還應在外層頁表項中增設一個狀態位S,其值若爲0,表示該頁表分頁還沒有調入內存,不然,說明已經在內存,進程運行時,地址變換機構根據邏輯地址P1,去查找外層頁表,若所找到的頁表項中的狀態位爲0,則產生一中斷信號,請求OS將該頁表分頁調入內存。
對於64位的機器而言,採用兩級頁表已經不太合適,若是頁面大小仍採用4KB,那麼剩下52位,若仍是按照物理塊的大小(2^12位)來劃分頁表,每一個頁表項4B,故一頁中可存放2^10個頁表項,則將餘下的42位用於外層頁號,此時,外層頁表中可能有4096G個頁表項,要佔用16384GB的連續內存空間,顯然是不行的。必須採用多級頁表,即將外層頁表再進行分頁。若計算機的虛擬地址空間大小爲2^64,頁面大小爲4KB,頁表項爲4B,則最少頁表的級數爲6級,首先總的頁面個數爲2^52(64 - 12),其次,每一個物理塊能裝入的頁表項爲4KB/4B = 2^10個,10 * 6 > 52,即最少須要6級。
6、基本分段存儲管理方式
從固定分區到動態分區分配,再到分頁存儲管理方式,其主要動力爲提升內存利用率,引入分段存儲管理的目的在於知足用戶在編程和使用上多方面的要求。如
① 方便編程,用戶能夠把本身的做業按照邏輯關係劃分爲若干段,每一個段都是從0開始編址,並有本身的名字和長度。
② 信息共享,在實現對程序和數據的共享時,是以信息的邏輯單位爲基礎的,好比共享某個函數。
③ 信息保護,信息保護一樣是對信息的邏輯單位進行保護。
④ 動態增加,在實際應用中,數據段在使用過程當中每每會不斷增加,而實現沒法確切知道數據段會增加到多大,分段能夠較好的解決這個問題。
⑤ 動態連接,再運行時,先將主程序所對應的目標程序裝入內存並啓動運行,當運行過程當中有須要調用某段時,纔將該段調入內存並進行連接。
6.1 分段系統的基本原理
在分段管理中,做業的地址空間被劃分爲若干個段,每一個段定義了一組邏輯信息,若有主程序段MAIN,子程序段X,數據段D及棧段S,每一個段都有本身的名字,每一個段從0開始編址,並採用一段連續的地址空間,段的長度由相應的邏輯信息組的長度決定,於是各段長度不等,整個做業的地址空間因爲是分紅多個段,於是是二維的,即其邏輯地址由段號和段內地址構成。
說明:一個做業容許最長有64K個段,每一個段的最大長度爲64KB。
在分段式存儲管理系統中,爲每一個分段分配一個連續的分區,而進程中的各個段能夠離散地移入內存中不一樣的分區,爲了使程序正常運行,可以物理內存中找出每一個邏輯段所對應的位置,應該爲每一個進程創建一張段映射表,稱爲段表,每一個段在表中有一個表項,其中記錄了該段在內存中的起始地址和段的長度。段表能夠存放在一組寄存器中,這樣有利於提升地址轉換速度,但一般將段表放在內存中。段表用於實現從邏輯段到物理內存區的映射。
爲了實現從進程的邏輯地址到物理地址的變換功能,在系統中設置了段表寄存器,用於存放段表始址和段表TL,在進行地址變換時,系統將邏輯地址中的段號與段表長度TL進行比較,若S>TL,表示段號太大,訪問越界,產生越界中斷信號,若未越界,則根據段表的始址和該段的段號,計算該段對應段表項的位置,從中讀出該段在內存中的起始地址,而後,再檢查段內地址d是否超過該段的段長SL,若超過,一樣發出越界中斷信號,若爲越界,則將該段的基址與段內地址d相加,即獲得要訪問的內存物理地址。
每次訪問一個數據時(需給出段號和段內地址),也須要訪問兩次內存,第一次根據段號得到基址,第二次根據基址與段內地址之和訪問真實數據的物理地址。這下降了計算機的速率,也能夠增設一個聯想存儲器,用來保存最近經常使用的段表項,用來加速存取數據的時間。
能夠看到,分頁與分段存在很大的類似性,如都採用離散分配方式,都須要經過地址映射機構實現地址變換,但二者的主要區別以下。
① 頁是信息的物理單位,分頁是爲實現離散分配方式,以消減內存的外零頭,提升內存的利用率,或者說,分頁僅僅是因爲系統管理的須要而不是用戶的須要,段則是信息的邏輯單位,它含有一組意義相對完整的信息,分段的目的是爲了能更好地知足用戶的須要。
② 頁的大小固定且由系統決定,由系統把邏輯地址劃分爲頁號和頁內地址兩部分,是由機器硬件實現的,一個系統中,只存在一種大小的頁面,段的長度則不固定,決定於用戶所編寫的程序,一般由編譯程序在對源程序進行編譯時,根據信息的性質來劃分。
③ 分頁的做業的地址空間是一維的,即單一的線性的地址空間,程序員只利用一個記憶符便可表示一個地址,而分段的做業地址空間是二維的,程序員在標識一個地址是,須要給出段名和段內地址。
6.2 段頁式存儲管理方式
分頁系統可以有效的提升內存利用率(可是會存在頁內碎片),分段系統則可以很好地知足用戶須要。若能將兩種方式結合起來,既具備分段系統的便於實現、分段可共享、易於保護、可動態連接等優勢,又能像分頁系統那樣很好地解決內存的外部碎片問題,基於此,提出了段頁式系統。
段頁式系統先將用戶程序分紅若干個段,再把段分爲若干個頁,併爲每個段賦予一個段名。段頁式系統中,地址結構由段號、段內頁號、頁內地址三部分構成。
在段頁式系統中,爲了便於實現地址轉換,須配置一個段表寄存器,其中存放段表始址和段表長TL,進行地址變換時,首先利用段號S,將它與段表長TL進行比較,若S<TL,表示未越界,因而利用段表始址和段號來求出該段所對應的段表項在段表中的位置,從中獲得該段的頁表始址,並利用邏輯地址中的段內頁號P來得到對應頁的頁表項位置,從中讀出該頁所在的物理塊號b,再利用b和頁內地址構成物理地址。
在段頁式系統中,爲了得到一條指令或數據,須要訪問內存三次,第一次訪問時訪問內存中的段表,從中取得頁表始址,第二次訪問是訪問內存中的頁表,從中取出該頁所在的物理塊號,並將該塊號與頁內地址一塊兒造成指令或數據的物理地址,第三次訪問纔是真正的從第二次訪問所得的地址中,取出指令或數據。一樣,也能夠增設高速緩衝寄存器用於加快訪問速度。
7、虛擬存儲器的基本概念
前面所介紹的存儲器管理方式都有一個共同的特色,即他們都要求將一個做業所有裝入內存後方能運行,因而,出現了下面兩種狀況
① 有的做業很大,其所要求的內存空間超過了內存總容量,做業不能所有被裝入內存,導致該做業沒法運行。
② 作大量做業要求運行,但因爲內存容量不足以容納全部這些做業,只能將少數做業裝入內存讓他們先運行,而將其餘大量做業留在外存上等待。
爲了解決上述問題,能夠增長物理內存,可是其不太現實,另外是從邏輯上擴充內存容量。
基於程序的局部性原理(時間侷限性和空閒侷限性),程序在運行以前,沒有必要所有裝入內存,僅需將那些當前要運行的少數頁面或段先裝入內存即可運行。其他部分暫留在磁盤上,程序運行時,若是它所要訪問的頁(段)已經調入內存,即可繼續執行下去,但若是程序所要訪問的頁(段)還沒有調入內存(缺頁或缺段),此時程序應利用OS的請求調頁(段)功能,將它們調入內存,以使進程繼續執行下去。若是此時內存已滿,沒法再裝入新的頁(段),則還需利用頁(段)的置換功能,將內存中暫時不用的頁(段)調至磁盤上,再將要訪問的頁(段)調入內存,使程序繼續執行。這樣,可使很大的用戶程序在較小的內存空間中運行。從用戶的調入看,該系統具備很大的內存容量,可是,用戶看到的大容量只是一種感受,這種存儲器被稱爲虛擬存儲器。所謂虛擬存儲器,是指具備請求調入功能和置換功能,能從邏輯上對內存容量加以擴充的一種存儲器系統,其邏輯容量由內存容量和外存容量之和決定,其運行速度接近內存,成本接近外存。
7.1 虛擬存儲器的實現方法
在虛擬存儲器中,容許將一個做業分屢次調入內存,其創建在離散分配的存儲管理方式上。
① 請求分頁系統,在分頁系統的基礎上,增長了請求調頁功能和頁面置換功能所造成的頁式虛擬存儲系統,其容許只裝入少許頁面的程序(數據),便啓動運行,之後,再經過調頁功能及頁面置換功能,陸續地把要運行的頁面調入內存,同時把暫時不用的頁面換出到外存,置換是以頁面爲單位。其須要必要的硬件和軟件支持。硬件有請求分頁的頁表機制(它是在純分頁的頁表機制上增長若干項而造成的,做爲請求分頁的數據結構)、缺頁中斷機構(每當用戶程序要訪問的頁面還沒有調入內存時,便產生一缺頁中斷,請求OS將所缺的頁調入內存)、地址變換機構(在純分頁的基礎上發展造成)。軟件有用於實現調頁的軟件和實現頁面置換的軟件。
② 請求分段系統,在分段系統的基礎上,增長了請求調段功能和分段置換功能所造成的段式虛擬存儲系統。其容許只裝入少許段的用戶程序和數據,便可啓動運行,之後再經過調段功能和段的置換功能將咱不運行的段調出,同時調入即將運行的段,置換是以段爲單位。其須要必要的硬件和軟件支持,硬件有請求分段的段表機制(它是在純分頁的段表機制上增長若干項而造成的,做爲請求分段的數據結構)、缺段中斷機構(每當用戶程序要訪問的段還沒有調入內存時,便產生一缺段中斷,請求OS將所缺的段調入內存)、地址變換機構(在純分段的基礎上發展造成)。軟件有用於實現調頁的軟件和實現頁面置換的軟件。
7.2 虛擬存儲器的特徵
① 屢次性,一個做業會被分紅屢次調入內存運行,屢次性是虛擬存儲器最重要的特徵。
② 對換性,容許在做業的運行過程當中進行換進、換出。換進換出可以有效地提升內存利用率。
③ 虛擬性,使用戶所看到的內存容量遠大於實際內存容量。
虛擬性是以屢次性和對換性爲基礎的,僅當系統容許將做業分屢次調入內存,並可以將內存中暫時不運行的程序和數據換至磁盤上時,纔有可能實現虛擬存儲器,而屢次性和對換性有必須創建在離散分配的基礎上。
8、請求分頁存儲管理方式
請求分頁是創建在分頁基礎上的,增長了請求調頁功能和頁面置換功能。
8.1 請求分頁中的硬件支持
① 頁表機制,其基本做用仍然是將用戶地址空間中的邏輯地址變換爲內存空間中的物理地址,因爲只將應用程序的一部分調入內存,還有一部分仍在盤上,故須要再頁表中再增長若干項,供程序(數據)在換進、換出時參考,請求分頁系統中的頁表項以下
說明:狀態位P,用於指示該頁是否已調入內存,供程序訪問時參考;訪問字段A,用於記錄本頁在一段時間內被訪問的次數,或記錄本頁最近已有多長時間未被訪問,供選擇換出頁面時參考;修改位M,表示該頁在調入內存後是否被修改過,因爲內存的每一頁在外存上保留有一個副本,所以,若未被修改,則在置換時就不須要再將該頁寫回到外存上,若被修改,則必須重寫到外存上,M位供置換頁面時參考;外存地址,指出該頁在外存上的地址,一般是物理塊號,供調入該頁時參考。
② 缺頁中斷機構,當要訪問的頁面不在內存時,產生一個缺頁中斷,請求OS將缺的頁面調入內存,缺頁做爲中斷,也須要通過保護CPU現場、分析中斷緣由、轉入中斷處理程序進行處理、恢復CPU環境等。可是,其與通常中斷相比有一些不一樣,主要在於:在指令執行期間產生和處理中斷信號(一般CPU都是在一條指令執行完後,才檢查是否有中斷請求到達,如有,則響應,不然,繼續執行下一條指令,然而,缺頁中斷是在指令執行期間,發現所要訪問的指令或數據再也不內存時所產生和處理的),一條指令在執行期間,可能產生屢次缺頁中斷。
③ 地址變換機構,在分頁系統地址變換基礎上,爲實現存儲器而增長的某些功能而造成。如產生和處理缺頁中斷,以及從內存中換出一頁功能等。
8.2 內存分配策略和分配算法
在爲進程分配內存時,涉及到以下三個問題:最小物理塊數的肯定、物理塊的分配策略、物理塊的分配算法。
① 最小物理塊數的肯定,指可以保證進程正常運行所需的最小物理塊數,當系統爲進程分配的物理塊數小於此值時,進程將沒法運行。進程應得到的最少物理塊數與計算機的硬件結構有關,取決於指令的格式、功能、尋址方式。
② 物理塊的分配策略,在請求分頁系統中,可採起兩種內存分配策略,固定和可變分配策略,在進行置換時,也可採用全局置換和局部置換,可組合出以下三種適用的策略。固定分配局部置換(爲每一個進程分配必定數目的物理塊,整個運行期再也不改變,若是進程在運行中發現缺頁,則只能從該進程在內存的n個頁面中選出一頁換出,而後再調入一頁,以保證分配給該進程的內存空間不變,若開始爲進程分配的物理塊數太少,則會頻繁缺頁,下降系統吞吐量,若太多,則使內存中駐留的進程數目減小,進而形成CPU空閒或其餘資源空閒的狀況),可變分配全局置換(先爲系統中的每一個進程分配必定數目的物理塊,而OS自身也保持一個空閒物理塊隊列,當某進程發現缺頁時,由系統從空閒物理塊隊列中取出一個物理塊分配給該進程,並將欲調入的缺頁裝入其中,僅當空閒物理隊列的物理塊用完時,OS才能從內存中選擇一頁調出,該頁多是系統中任一進程的頁,這樣,會是那個進程的物理塊減小,進而使缺頁率增長),可變分配局部置換(爲每一個進程分配必定數目的物理塊,當進程缺頁時,只容許從該進程在內存中的頁面中選出一頁換出,這樣不會影響其餘進程的運行,若是該進程頻繁發生缺頁,則系統須要再爲該進程分配若干附加的物理塊,直至該進程的缺頁率減小到適當程度爲止,反之,若一個進程正在運行過程當中的缺頁率特別低,則此時可適當減小分配給該進程的物理塊數,但不該該引發缺頁率明顯增長)。
③ 物理塊分配算法,可採用平均分配算法(將系統中全部可供分配的物理塊平均分配給各個進程)、按比例分配(根據進程的大小按比例分配物理塊)、考慮優先權的分配算法(將重要的,緊迫的做業分配較多的內存空間,可將系統的物理塊分紅兩部分,一部分按比例分配給各進程,另外一部分則根據進程的優先權適當地增長相應份額後,分配給進程)
9、頁面置換算法
在進程運行過程當中,若其所要訪問的頁面不在內存而需把它們調入內存,但內存已五空閒空間時,爲了保證該進程能正常運行,系統必須從內存中調出一頁程序或數據送磁盤的對換區中,但應將哪一個頁面調出,必須根據必定的算法來肯定,一般,把選擇換出頁面的算法稱爲頁面置換算法,置換算法的好壞,直接影響到系統的性能。一個好的頁面置換算法,應該具備較低的頁面更換頻率。
9.1 最佳置換算法
是一種理論上的算法,所選擇的被淘汰頁面將是之後用不使用的,或者是在最長時間內再也不被訪問的,採用最佳置換算法,能夠保證得到最低的缺頁率,因爲沒法預知一個進程在內存的若干個頁面中,哪一個頁面是將來最長時間內再也不被訪問的,於是該算法沒法實現,但能夠以此評價其餘算法。假設系統爲某進程分配了三個物理塊,並考慮以下的頁面號引用串:7, 0 ,1, 2, 0, 3, 0, 4, 2, 3, 0, 3, 2, 1, 2, 0, 1, 7, 0, 1。在進程運行後的置換以下圖。
採用最佳置換算法發生了6次頁面置換。
9.2 先進先出頁面(FIFO)置換算法
該算法老是淘汰最早進入內存的頁面,即選擇在內存中駐留時間最久的頁面予以淘汰,該算法實現簡單,只須要把一個進程已調入內存的頁面,按照前後次序連接成一個隊列,並設置一個指針,稱爲替換指針,使之指向最老的頁面,但該算法與進程實際運行的規律不相適應,由於在進程中,有些頁面常常被訪問,FIFO算法並不能保證這些頁面不被淘汰。
使用FIFO算法時進行了12次頁面置換。
9.3 最近最久未使用(LRU)置換算法
該算法根據頁面調入內存後的使用狀況來進行決策,因爲沒法預測各頁面未來的使用狀況,LRU只能使用最近的過去代替最近的未來,所以,LRU置換算法是選擇最近最久未使用的頁面予以淘汰。該算法賦予每一個頁面一個訪問字段,用來記錄一個頁面自上次訪問以來所經歷的時間t,當須要淘汰一個頁面時,選擇現有頁面中其t值最大的,即最近最久未使用的頁面予以淘汰。
使用LRU算法時進行了9次頁面置換。
9.4 Clock置換算法
爲每一頁設置一位訪問位,再將內存中的全部頁面都經過連接指針連接成一個循環隊列,當某頁被訪問時,其訪問位置爲1,置換算法在選擇一頁淘汰時,只須要檢查頁的訪問位,若是是0,就選擇該頁換出;若爲1,則從新置爲0,暫不換出,給該頁第二次駐留內存的機會,再按照FIFO算法檢查下一頁面。當檢查到隊列中的最後一個頁面時,若其訪問位仍然是1,則再返回到隊首去檢查第一個頁面,該算法只有一位訪問位,只能用它表示該頁是否已經使用過,而置換時是將未使用過的頁面置換出去,故又把該算法稱爲最近未用算法NRU(Not Recently Used)
在將一個頁面換出時,若是該頁已經被修改過,便須要將該頁從新寫回到磁盤上,但若是沒有被修改過,則沒必要將它拷回磁盤,在改進的Clock算法中,增長了一個置換代價的因素,這樣,選擇頁面換出時,既要是未使用過的頁面,又是要未被修改過的頁面,把同時知足這兩個條件的頁面做爲首選淘汰頁面。由訪問位A和修改位M能夠組合以下四種類型的頁面
① (A = 0, M = 0),表示該頁最近既未被訪問,又未被修改,是最佳淘汰頁面。
② (A = 0, M = 1),表示該頁最近未被訪問,但已被修改,並非很好的淘汰頁面。
③ (A = 1, M = 0),表示該頁最近已被訪問,但未被修改,該頁可能被再次訪問。
④ (A = 1, M = 1),表示該頁最近已被訪問且被修改,該頁可能再被訪問。
對於置換而言,執行以下幾步。
① 從指針所指示的當前位置開始,掃描循環隊列,尋找A = 0 且 M = 0的第一類頁面,將所遇到的第一個頁面做爲所選中的淘汰頁,在第一次掃描期間不改變訪問位A。
② 若是第一步失敗,即查找一週後未遇到第一類頁面,則開始第二輪掃描,尋找A = 0 且 M = 1的第二類頁面,將所遇到的第一個這類頁面做爲淘汰頁。在第二輪掃描期間,將全部掃描過的頁面的訪問位置爲0。
③ 若是第二步也失敗,即未找到第二類頁面,則將指針返回到開始位置,並將全部的訪問位復爲0,而後重複第一步,若是仍然失敗,則重複第二步,則必定可以找到被淘汰的頁。
10、請求分段存儲管理方式
只需先調入若干個分段即可啓動運行,當所訪問的段不在內存中時,可請求OS將所缺的段調入內存。也一樣須要硬件的支持。
10.1 請求分段中的硬件支持
爲了快速完成請求分段功能,須要支持的硬件有段表機制、缺段中斷機制、地址變換機構。
① 段表機制,因爲只有一部分段裝入內存,其他段仍留在外存上,須要再段表中增長若干項,以供程序調進、調出時參考。
說明:各字段意義以下存取方式(用於標識本分段的存取屬性是隻執行、只讀、仍是容許讀/寫),訪問字段A(用於記錄該段被訪問的頻繁程度),修改位M(表示該頁在進入內存後是否已被修改過,供置換時參考),存在位P(表示本段是否已調入內存,供程序訪問時參考),增補位(用於表示本段在運行過程當中是否作過動態增加),外存始址(本段在外存中的起始地址,即起始盤塊號)。
② 缺頁中斷機構,進程運行時發現所需的段還沒有調入內存,便由缺段中斷機構產生一個缺段中斷信號,進入OS後由缺段中斷處理程序將所須要的段調入內存。須要在一條指令的執行期間,產生和處理中斷,以及一條指令執行期間,可能會產生屢次缺段中斷。
③ 地址變換機構,其在分段系統地址變換機構基礎上造成,增長了缺段中斷的請求和處理功能。
11、總結
通過本篇博客,明白了OS如何對存儲器進行高效管理,其中有不少細節直接咱們去好好思考,也謝謝各位園友的觀看~