❶ 操作系統(四)文件管理
文件—就是一組有意義的信息/數據集合
文件屬於抽象數據類型。為了恰當地定義文件,需要考慮有關文件的操作。操作系統提供系統調用,它對文件進行創建、寫、讀、重定位、搠除和截斷等操作。
所謂的「邏輯結構」,就是指在用戶看來,文件內部的數據應該是如何組織起來的。而「物理結構」指的是在操作系統看來,文件的數據是如何存放在外存中的。
無結構文件:文件內部的數據就是一系列二進制流或字元流組成。又稱「流式文件」
文件內部的數據其實就是一系列字元流,沒有明顯的結構特性。因此也不用探討無結構文件的「邏輯結構」問題。
有結構文件:由一組相似的記錄組成,又稱「記錄式文件」。每條記錄又若干個數據項組成。 [1] 一般來說,每條記錄有一個數據項可作為關鍵字。根據各條記錄的長度(佔用的存儲空間)是否相等,又可分為定長記錄和可變長記錄兩種。有結構文件按記錄的組織形式可以分為:
對於含有N條記錄的順序文件,查找某關鍵字值的記錄時,平均需要查找N/2次。在索引順序文件中,假設N條記錄分為√N組,索引表中有√N個表項,每組有√N條記錄,在查找某關鍵字值的記錄時,先順序查找索引表,需要查找√N /2次,然後在主文件中對應的組中順序查找,也需要查找√N/2次,因此共需查找√N/2+√N/2=√N次。顯然,索引順序文件提高了查找效率,若記錄數很多,則可採用兩級或多級索引
FCB的有序集合稱為「文件目錄」,一個FCB就是一個文件目錄項。FCB中包含了文件的基本信息(文件名、物理地址、邏輯結構、物理結構等),存取控制信息(是否可讀/可寫、禁止訪問的用戶名單等),使用信息(如文件的建立時間、修改時間等)。最重要,最基本的還是文件名、文件存放的物理地址。
對目錄的操作如下:
操作的時候,可以有以下幾種目錄結構:
早期操作系統並不支持多級目錄,整個系統中只建立一張目錄表,每個文件佔一個目錄項。
單級目錄實現了「按名存取」,但是不允許文件重名。在創建一個文件時,需要先檢查目錄表中有沒有重名文件,確定不重名後才能允許建立文件,並將新文件對應的目錄項插入目錄表中。顯然, 單級目錄結構不適用於多用戶操作系統。
早期的多用戶操作系統,採用兩級目錄結構。分為主文件目錄(MFD,Master File Directory)和用戶文件目錄(UFD,User Flie Directory)。
允許不同用戶的文件重名。文件名雖然相同,但是對應的其實是不同的文件。兩級目錄結構允許不同用戶的文件重名,也可以在目錄上實現實現訪問限制(檢查此時登錄的用戶名是否匹配)。但是兩級目錄結構依然缺乏靈活性,用戶不能對自己的文件進行分類
用戶(或用戶進程)要訪問某個文件時要用文件路徑名標識文件,文件路徑名是個字元串。各級目錄之間用「/」隔開。從根目錄出發的路徑稱為絕對路徑。
系統根據絕對路徑一層一層地找到下一級目錄。剛開始從外存讀入根目錄的目錄表;找到目錄的存放位置後,從外存讀入對應的目錄表;再找到目錄的存放位置,再從外存讀入對應目錄表;最後才找到文件的存放位置。整個過程需要3次讀磁碟I/O操作。
很多時候,用戶會連續訪問同一目錄內的多個文件,顯然,每次都從根目錄開始查找,是很低效的。因此可以設置一個「當前目錄」。此時已經打開了的目錄文件,也就是說,這張目錄表已調入內存,那麼可以把它設置為「當前目錄」。當用戶想要訪問某個文件時,可以使用從當前目錄出發的「相對路徑」
可見,引入「當前目錄」和「相對路徑」後,磁碟I/O的次數減少了。這就提升了訪問文件的效率。
樹形目錄結構可以很方便地對文件進行分類,層次結構清晰,也能夠更有效地進行文件的管理和保護。但是,樹形結構不便於實現文件的共享。為此,提出了「無環圖目錄結構」。
可以用不同的文件名指向同一個文件,甚至可以指向同一個目錄(共享同一目錄下的所有內容)。需要為每個共享結點設置一個共享計數器,用於記錄此時有多少個地方在共享該結點。用戶提出刪除結點的請求時,只是刪除該用戶的FCB、並使共享計數器減1,並不會直接刪除共享結點。只有共享計數器減為0時,才刪除結點。
其實在查找各級目錄的過程中只需要用到「文件名」這個信息,只有文件名匹配時,才需要讀出文件的其他信息。因此可以考慮讓目錄表「瘦身」來提升效率。
當找到文件名對應的目錄項時,才需要將索引結點調入內存,索引結點中記錄了文件的各種信息,包括文件在外存中的存放位置,根據「存放位置」即可找到文件。存放在外存中的索引結點稱為「磁碟索引結點」,當索引結點放入內存後稱為「內存索引結點」。相比之下內存索引結點中需要增加一些信息,比如:文件是否被修改、此時有幾個進程正在訪問該文件等。
為文件設置一個「口令」(如:abc112233),用戶請求訪問該文件時必須提供「口令」。
優點:保存口令的空間開銷不多,驗證口令的時間開銷也很小。
缺點:正確的「口令」存放在系統內部,不夠安全。
使用某個「密碼」對文件進行加密,在訪問文件時需要提供正確的「密碼」才能對文件進行正確的解密。 [3]
優點:保密性強,不需要在系統中存儲「密碼」
缺點:編碼/解碼,或者說加密/解密要花費一定時間。
在每個文件的FCB(或索引結點)中增加一個訪問控制列表(Access-Control List, ACL),該表中記錄了各個用戶可以對該文件執行哪些操作。
有的計算機可能會有很多個用戶,因此訪問控制列表可能會很大,可以用精簡的訪問列表解決這個問題
精簡的訪問列表:以「組」為單位,標記各「組」用戶可以對文件執行哪些操作。當某用戶想要訪問文件時,系統會檢查該用戶所屬的分組是否有相應的訪問許可權。
索引結點,是一種文件目錄瘦身策略。由於檢索文件時只需用到文件名,因此可以將除了文件名之外的其他信息放到索引結點中。這樣目錄項就只需要包含文件名、索引結點指針。
索引結點中設置一個鏈接計數變數count,用於表示鏈接到本索引結點上的用戶目錄項數。
當User3訪問「ccc」時,操作系統判斷文件「ccc」屬於Link類型文件,於是會根據其中記錄的路徑層層查找目錄,最終找到User1的目錄表中的「aaa」表項,於是就找到了文件1的索引結點。
類似於內存分頁,磁碟中的存儲單元也會被分為一個個「塊/磁碟塊/物理塊」。很多操作系統中,磁碟塊的大小與內存塊、頁面的大小相同
內存與磁碟之間的數據交換(即讀/寫操作、磁碟I/O)都是以「塊」為單位進行的。即每次讀入一塊,或每次寫出一塊
在內存管理中,進程的邏輯地址空間被分為一個一個頁面同樣的,在外存管理中,為了方便對文件數據的管理,文件的邏輯地址空間也被分為了一個一個的文件「塊」。於是文件的邏輯地址也可以表示為(邏輯塊號,塊內地址)的形式。用戶通過邏輯地址來操作自己的文件,操作系統要負責實現從邏輯地址到物理地址的映射
連續分配方式要求每個文件在磁碟上佔有一組連續的塊。用戶給出要訪問的邏輯塊號,操作系統找到該文件對應的目錄項(FCB)——可以直接算出邏輯塊號對應的物理塊號,物理塊號=起始塊號+邏輯塊號。還需要檢查用戶提供的邏輯塊號是否合法(邏輯塊號≥ 長度就不合法)因此 連續分配支持順序訪問和直接訪問 (即隨機訪問)
讀取某個磁碟塊時,需要移動磁頭。訪問的兩個磁碟塊相隔越遠,移動磁頭所需時間就越長。 連續分配的文件在順序讀/寫時速度最快,物理上採用連續分配的文件不方便拓展,且存儲空間利用率低,會產生難以利用的磁碟碎片可以用緊湊來處理碎片,但是需要耗費很大的時間代價。。
鏈接分配採取離散分配的方式,可以為文件分配離散的磁碟塊。分為隱式鏈接和顯式鏈接兩種。
用戶給出要訪問的邏輯塊號i,操作系統找到該文件對應的目錄項(FCB)…從目錄項中找到起始塊號(即0號塊),將0號邏輯塊讀入內存,由此知道1號邏輯塊存放的物理塊號,於是讀入1號邏輯塊,再找到2號邏輯塊的存放位置……以此類推。因此,讀入i號邏輯塊,總共需要i+1次磁碟I/O。
採用鏈式分配(隱式鏈接)方式的文件,只支持順序訪問,不支持隨機訪問,查找效率低。另外,指向下一個盤塊的指針也需要耗費少量的存儲空間。但是,採用隱式鏈接的鏈接分配方式,很方便文件拓展。另外,所有的空閑磁碟塊都可以被利用,不會有碎片問題,外存利用率高。
把用於鏈接文件各物理塊的指針顯式地存放在一張表中。即文件分配表(FAT,File Allocation Table)
一個磁碟僅設置一張FAT 。開機時,將FAT讀入內存,並常駐內存。FAT的各個表項在物理上連續存儲,且每一個表項長度相同,因此「物理塊號」欄位可以是隱含的。
從目錄項中找到起始塊號,若i>0,則查詢內存中的文件分配表FAT,往後找到i號邏輯塊對應的物理塊號。 邏輯塊號轉換成物理塊號的過程不需要讀磁碟操作。
採用鏈式分配(顯式鏈接)方式的文件,支持順序訪問,也支持隨機訪問 (想訪問i號邏輯塊時,並不需要依次訪問之前的0 ~ i-1號邏輯塊), 由於塊號轉換的過程不需要訪問磁碟,因此相比於隱式鏈接來說,訪問速度快很多。顯然,顯式鏈接也不會產生外部碎片,也可以很方便地對文件進行拓展。
索引分配允許文件離散地分配在各個磁碟塊中,系統會為每個文件建立一張索引表,索引表中記錄了文件的各個邏輯塊對應的物理塊(索引表的功能類似於內存管理中的頁表——建立邏輯頁面到物理頁之間的映射關系)。索引表存放的磁碟塊稱為索引塊。文件數據存放的磁碟塊稱為數據塊。
在顯式鏈接的鏈式分配方式中,文件分配表FAT是一個磁碟對應一張。而索引分配方式中,索引表是一個文件對應一張。可以用固定的長度表示物理塊號 [4] ,因此,索引表中的「邏輯塊號」可以是隱含的。
用戶給出要訪問的邏輯塊號i,操作系統找到該文件對應的目錄項(FCB)…從目錄項中可知索引表存放位置,將索引表從外存讀入內存,並查找索引表即可只i號邏輯塊在外存中的存放位置。
可見, 索引分配方式可以支持隨機訪問。文件拓展也很容易實現 (只需要給文件分配一個空閑塊,並增加一個索引表項即可)但是 索引表需要佔用一定的存儲空間
索引塊的大小是一個重要的問題,每個文件必須有一個索引塊,因此索引塊應盡可能小,但索引塊太小就無法支持大文件,可以採用以下機制:
空閑表法適用於「連續分配方式」。分配磁碟塊:與內存管理中的動態分區分配很類似,為一個文件分配連續的存儲空間。同樣可採用首次適應、最佳適應、最壞適應等演算法來決定要為文件分配哪個區間。回收磁碟塊:與內存管理中的動態分區分配很類似,當回收某個存儲區時需要有四種情況——①回收區的前後都沒有相鄰空閑區;②回收區的前後都是空閑區;③回收區前面是空閑區;④回收區後面是空閑區。總之,回收時需要注意表項的合並問題。
操作系統保存著鏈頭、鏈尾指針。如何分配:若某文件申請K個盤塊,則從鏈頭開始依次摘下K個盤塊分配,並修改空閑鏈的鏈頭指針。如何回收:回收的盤塊依次掛到鏈尾,並修改空閑鏈的鏈尾指針。適用於離散分配的物理結構。為文件分配多個盤塊時可能要重復多次操作
操作系統保存著鏈頭、鏈尾指針。如何分配:若某文件申請K個盤塊,則可以採用首次適應、最佳適應等演算法,從鏈頭開始檢索,按照演算法規則找到一個大小符合要求的空閑盤區,分配給文件。若沒有合適的連續空閑塊,也可以將不同盤區的盤塊同時分配給一個文件,注意分配後可能要修改相應的鏈指針、盤區大小等數據。如何回收:若回收區和某個空閑盤區相鄰,則需要將回收區合並到空閑盤區中。若回收區沒有和任何空閑區相鄰,將回收區作為單獨的一個空閑盤區掛到鏈尾。 離散分配、連續分配都適用。為一個文件分配多個盤塊時效率更高
位示圖:每個二進制位對應一個盤塊。在本例中,「0」代表盤塊空閑,「1」代表盤塊已分配。位示圖一般用連續的「字」來表示,如本例中一個字的字長是16位,字中的每一位對應一個盤塊。因此可以用(字型大小,位號)對應一個盤塊號。當然有的題目中也描述為(行號,列號)
盤塊號、字型大小、位號從0開始,若n表示字長,則
如何分配:若文件需要K個塊,①順序掃描位示圖,找到K個相鄰或不相鄰的「0」;②根據字型大小、位號算出對應的盤塊號,將相應盤塊分配給文件;③將相應位設置為「1」。如何回收:①根據回收的盤塊號計算出對應的字型大小、位號;②將相應二進制位設為「0」
空閑表法、空閑鏈表法不適用於大型文件系統,因為空閑表或空閑鏈表可能過大。UNIX系統中採用了成組鏈接法對磁碟空閑塊進行管理。文件卷的目錄區中專門用一個磁碟塊作為「超級塊」,當系統啟動時需要將超級塊讀入內存。並且要保證內存與外存中的「超級塊」數據一致。
進行Create系統調用時,需要提供的幾個主要參數:
操作系統在處理Create系統調用時,主要做了兩件事:
進行Delete系統調用時,需要提供的幾個主要參數:
操作系統在處理Delete系統調用時,主要做了幾件
事:
在很多操作系統中,在對文件進行操作之前,要求用戶先使用open系統調用「打開文件」,需要提供的幾個主要參數:
操作系統在處理open系統調用時,主要做了幾件事:
進程使用完文件後,要「關閉文件」
操作系統在處理Close系統調用時,主要做了幾件事:
進程使用read系統調用完成寫操作。需要指明是哪個文件(在支持「打開文件」操作的系統中,只需要提供文件在打開文件表中的索引號即可),還需要指明要讀入多少數據(如:讀入1KB)、指明讀入的數據要放在內存中的什麼位置。操作系統在處理read系統調用時,會從讀指針指向的外存中,將用戶指定大小的數據讀入用戶指定的內存區域中。
進程使用write系統調用完成寫操作,需要指明是哪個文件(在支持「打開文件」操作的系統中,只需要提供文件在打開文件表中的索引號即可),還需要指明要寫出多少數據(如:寫出1KB)、寫回外存的數據放在內存中的什麼位置操作系統在處理write系統調用時,會從用戶指定的內存區域中,將指定大小的數據寫回寫指針指向的外存。
尋找時間(尋道時間)T S :在讀/寫數據前,將磁頭移動到指定磁軌所花的時間。
延遲時間T R :通過旋轉磁碟,使磁頭定位到目標扇區所需要的時間。設磁碟轉速為r(單位:轉/秒,或轉/分),則平均所需的延遲時間
傳輸時間T t :從磁碟讀出或向磁碟寫入數據所經歷的時間,假設磁碟轉速為r,此次讀/寫的位元組數為b,每個磁軌上的位元組數為N。則
總的平均存取時間Ta
延遲時間和傳輸時間都與磁碟轉速相關,且為線性相關。而轉速是硬體的固有屬性,因此操作系統也無法優化延遲時間和傳輸時間,但是操作系統的磁碟調度演算法會直接影響尋道時間
根據進程請求訪問磁碟的先後順序進行調度。
優點:公平;如果請求訪問的磁軌比較集中的話,演算法性能還算過的去
缺點:如果有大量進程競爭使用磁碟,請求訪問的磁軌很分散,則FCFS在性能上很差,尋道時間長。
SSTF演算法會優先處理的磁軌是與當前磁頭最近的磁軌。可以保證每次的尋道時間最短,但是並不能保證總的尋道時間最短。(其實就是貪心演算法的思想,只是選擇眼前最優,但是總體未必最優)
優點:性能較好,平均尋道時間短
缺點:可能產生「飢餓」現象
SSTF演算法會產生飢餓的原因在於:磁頭有可能在一個小區域內來回來去地移動。為了防止這個問題,可以規定,只有磁頭移動到最外側磁軌的時候才能往內移動,移動到最內側磁軌的時候才能往外移動。這就是掃描演算法(SCAN)的思想。由於磁頭移動的方式很像電梯,因此也叫電梯演算法。
優點:性能較好,平均尋道時間較短,不會產生飢餓現象
缺點:①只有到達最邊上的磁軌時才能改變磁頭移動方向②SCAN演算法對於各個位置磁軌的響應頻率不平均
掃描演算法(SCAN)中,只有到達最邊上的磁軌時才能改變磁頭移動方向,事實上,處理了184號磁軌的訪問請求之後就不需要再往右移動磁頭了。LOOK調度演算法就是為了解決這個問題,如果在磁頭移動方向上已經沒有別的請求,就可以立即改變磁頭移動方向。(邊移動邊觀察,因此叫LOOK)
優點:比起SCAN演算法來,不需要每次都移動到最外側或最內側才改變磁頭方向,使尋道時間進一步縮短
SCAN演算法對於各個位置磁軌的響應頻率不平均,而C-SCAN演算法就是為了解決這個問題。規定只有磁頭朝某個特定方向移動時才處理磁軌訪問請求,而返回時直接快速移動至起始端而不處理任何請求。
優點:比起SCAN來,對於各個位置磁軌的響應頻率很平均。
缺點:只有到達最邊上的磁軌時才能改變磁頭移動方向,另外,比起SCAN演算法來,平均尋道時間更長。
C-SCAN演算法的主要缺點是只有到達最邊上的磁軌時才能改變磁頭移動方向,並且磁頭返回時不一定需要返回到最邊緣的磁軌上。C-LOOK演算法就是為了解決這個問題。如果磁頭移動的方向上已經沒有磁軌訪問請求了,就可以立即讓磁頭返回,並且磁頭只需要返回到有磁軌訪問請求的位置即可。
優點:比起C-SCAN演算法來,不需要每次都移動到最外側或最內側才改變磁頭方向,使尋道時間進一步縮短
磁碟地址結構的設計:
Q:磁碟的物理地址是(柱面號,盤面號,扇區號)而不是(盤面號,柱面號,扇區號)
A:讀取地址連續的磁碟塊時,採用(柱面號,盤面號,扇區號)的地址結構可以減少磁頭移動消耗的時間
減少延遲時間的方法:
Step 1:進行低級格式化(物理格式化),將磁碟的各個磁軌劃分為扇區。一個扇區通常可分為頭、數據區域(如512B大小)、尾三個部分組成。管理扇區所需要的各種數據結構一般存放在頭、尾兩個部分,包括扇區校驗碼(如奇偶校驗、CRC循環冗餘校驗碼等,校驗碼用於校驗扇區中的數據是否發生錯誤)
Step 2:將磁碟分區,每個分區由若干柱面組成(即分為我們熟悉的C盤、D盤、E盤)
Step 3:進行邏輯格式化,創建文件系統。包括創建文件系統的根目錄、初始化存儲空間管理所用的數據結構(如位示圖、空閑分區表)
計算機開機時需要進行一系列初始化的工作,這些初始化工作是通過執行初始化程序(自舉程序)完成的
初始化程序可以放在ROM(只讀存儲器)中。ROM中的數據在出廠時就寫入了,並且以後不能再修改。ROM中只存放很小的「自舉裝入程序」,完整的自舉程序放在磁碟的啟動塊(即引導塊/啟動分區)上,啟動塊位於磁碟的固定位置,開機時計算機先運行「自舉裝入程序」,通過執行該程序就可找到引導塊,並將完整的「自舉程序」讀入內存,完成初始化。擁有啟動分區的磁碟稱為啟動磁碟或系統磁碟(C:盤)
對於簡單的磁碟,可以在邏輯格式化時(建立文件系統時)對整個磁碟進行壞塊檢查,標明哪些扇區是壞扇區,比如:在FAT表上標明。(在這種方式中,壞塊對操作系統不透明)。
對於復雜的磁碟,磁碟控制器(磁碟設備內部的一個硬體部件)會維護一個壞塊鏈表。在磁碟出廠前進行低級格式化(物理格式化)時就將壞塊鏈進行初始化。會保留一些「備用扇區」,用於替換壞塊。這種方案稱為扇區備用。且這種處理方式中,壞塊對操作系統透明
❷ 在分頁存儲管理方式下應怎樣實現主存空間的分配和回收
2.1 模擬包括3部分:
1)實現特定的內存分配演算法
2)實現內存回收模擬
3)每種內存分配策略對應的碎片數統計
2.2 固定分區存儲管理
假設內存容量為120KB,並且分別劃分成8,16,32,64KB大小的塊各一塊。
一個進程所需要的內存為0到100個KB。同時假設一個進程在運行過程中所需內存的大小不變。
模擬五個進程到達請求分配與運行完回收情況,輸出主存分配表.
2.3 動態分區分配存儲管理
採用連續分配方式之動態分區分配存儲管理,使用首次適應演算法、下次適應演算法、最佳適應演算法和最壞適應演算法4種演算法完成設計(任選兩種演算法)。
❸ 主存空間的分配和回收,
#include "iostream.h"
#include "iomanip.h"
#define nofreearea 2
#define noadequacyarea 3
#define allocated 4
#define noprocess 2
#define nosuchprocess 3
#define reclaimed 4
typedef struct TUN
{
int address;
int size;
char name;
struct TUN *next;
} usedarea , *usedtable;
typedef struct TFN
{
int address;
int size;
struct TFN *next;
} freearea, *freetable;
usedtable usedTable = NULL;
freetable freeTable = NULL;
int alloc( char processname , int processsize )
{
if( freeTable == NULL )
return 1;
freetable p = freeTable;
freetable q = p;
while( p != NULL && p->size < processsize )
{
q = p;
p = p->next;
}
if( p == NULL )
return 3;
usedtable x = new usedarea;
x->address = p->address;
x->size = processsize;
x->name = processname;
x->next = NULL;
if( p->size > processsize )
{
p->size -= processsize;
p->address += processsize;
}
else
{
if( p == freeTable )
freeTable = NULL;
else
q->next = p->next;
delete p;
}
usedtable r = usedTable;
usedtable t = r;
while( r != NULL && r->address < x->address )
{
t = r;
r = r->next;
}
if( usedTable == NULL )
usedTable = x;
else
{
x->next = r;
t->next = x;
}
return 4;
}
int Reclaim( char processname )
{
if( usedTable == NULL )
return 1;
usedtable p = usedTable;
usedtable q = p;
while( p != NULL && p->name != processname )
{
q = p;
p = p->next;
}
if( p == NULL )
return 3;
freetable r = freeTable;
freetable t = r;
freetable x;
while( r != NULL && r->address < p->address )
{
t = r;
r = r->next;
}
x = new freearea;
x->address = p->address;
x->size = p->size;
x->next = NULL;
if( r == freeTable )
{
x->next = r;
freeTable = x;
t = freeTable;
}
else
{
x->next = r;
t->next = x;
}
while( t->next != NULL && t->address + t->size == t->next->address )
{
t->size += t->next->size;
r = t->next;
t->next = t->next->next;
delete r;
}
if( p == usedTable )
{
usedTable = usedTable->next;
}
else
q->next = p->next;
delete p;
return 4;
}
int Init()
{
freeTable = new freearea;
freeTable->address = 0;
freeTable->size = 128;
freeTable->next = NULL;
return 1;
}
void processrequest()
{
char processname;
int processsize;
cout<<"...................."<<endl;
cout<<"作業名: ";
cin >> processname;
cout<<"作業長度: ";
cin >> processsize;
if(processsize<=128)
{int i;
if( alloc( processname , processsize) == 4 )
{
i=i+processsize;
if(i>128)
{cout<<"該作業超出空間"<<endl;
}
if(i<=128)
cout<<"該作業已成功獲得所需空間"<<endl;
i=i+processsize;
cout<<"........................................"<<endl;
}
else
cout<<"該作業超出空間,沒有獲得所需空間"<<endl;
cout<<"........................................"<<endl;
return;
}
if(processsize>128)
{cout<<"該作業超出空間"<<endl;
cout<<"........................................"<<endl;
}
}
void processreclaim()
{
int processname;
cout<<"...................."<<endl;
cout<<"作業名: ";
cin >>processname;
int result = Reclaim( processname );
if( result == 4 )
cout<<"該作業已成功回收"<<endl;
else if( result == 2 || result == 1 )
cout<<"系統沒有作業或該作業不存在"<<endl;
cout<<"...................."<<endl;
}
void freeTablePrint()
{
cout<<endl<<endl<<endl<<"***********************************"<<endl;
cout<<setw(10)<<"address"<<setw(10)<<"length"<<setw(10)<<"state"<<endl<<endl;
freetable p = freeTable;
usedtable q = usedTable;
int x , y;
while( p || q )
{
if( p )
x = p->address;
else
x = 0x7fffffff;
if( q )
y = q->address;
else
y = 0x7fffffff;
if( x < y )
{
cout<<setw(10)<<p->address<<setw(10)<<p->size<<setw(10)<<"空閑"<<endl;
p = p->next;
}
if( x > y )
{
cout<<setw(10)<<q->address<<setw(10)<<q->size<<setw(10)<<"已分配"<<setw(10)<<"ID="<<q->name<<endl;
q = q->next;
}
}
cout<<endl<<endl<<endl<<"************************************"<<endl<<endl<<endl;
}
void main()
{
Init();
int choose;
bool exitFlag = false;
while( !exitFlag )
{
cout<<"************************0 - 退出 ************************"<<endl;
cout<<"************************1 - 分配主存 ************************"<<endl;
cout<<"************************2 - 回收主存 ************************"<<endl;
cout<<"************************3 - 顯示主存 ************************"<<endl<<endl<<endl;
cout<<"************************選擇所要執行的操作:";
cin>>choose;
switch( choose )
{
case 0:
exitFlag = true;
break;
case 1:
processrequest();
break;
case 2:
processreclaim();
break;
case 3:
freeTablePrint();
break;
}
}
}
❹ 存儲器管理的連續分配存儲管理方式有哪些
連續分配方式.它是指為了一個用戶程序分配一個連續的內存空間.可以分為單一連續分配、固定分區分配、動態分區分配以及動態重定位分區分配四種方式。不過今天我們講的是固定分區分配和動態分區分配。
固定分區分配是最簡單的一種可運行多道程序的存儲管理方式。 一、基本思想:在系統中把用戶區預先劃分成若干個固定分區(每個分區首地址固定,每個分區長度是固定),每個分區可供一個用戶程序獨占使用。注意:每個分區大小可以相同,也可以不相同。 二、主存分配與回收:藉助主存分配表。 三、地址轉換(靜態重定位):物理地址=分區起始地址+邏輯地址。其中劃分分區方法包括分區大小相等和分區大小不等。
動態分區分配是根據進程的實際需要,動態地為之分配內存空間。一、基本思想:按用戶程序需求動態劃分主存供用戶程序使用。(每個分區首地址是動態的,每個分區的長度也是動態的) 二、主存分配與回收-->(1)未分配表(登記未分配出去的分區情況);(2)已分配表(登記已經分配出去的分區情況)。 三、地址轉換:物理地址=分區起始地址+邏輯地址。 四、分區分配演算法:從空閑分區中選擇分區分www.hbbz08.com 配給用戶程序的策略。 (1)首次適應演算法(最先適應)順序查詢為分配表,從表中找出第一個可以滿足作業申請的分區劃分部分分配給用戶作業。 (2)循環首次適應演算法 (3)最佳適應演算法:從空閑分區中找出一個能滿足用戶作業申請的最小空閑分區劃分給用戶作業使用(有利於大作業執行) (4)最壞適應演算法:從空閑分區中挑最大的分區劃分給用戶程序使用(有利於中、小作業執行)
❺ 存儲器管理的幾種動態分區分配演算法有什麼特點優缺點都是什麼
動態分區分配演算法:
1.首次適應演算法(FF/first fit)
2.循環首次適應演算法(next fit)
3.最佳適應演算法(best fit)
從最小的分區開始分配
4.最壞適應演算法(worst fit)
從最大的分區開始分配
5.快速適應演算法/分類搜索法(quick fit)
將空閑分區根據其容量的大小進行分類
❻ 操作系統存儲器動態分區分配的(快速適應演算法)問題
這里的分割指的是:如果空閑分區大小為8k,而程序所佔有的大小隻有6k,對於一般的分配演算法,會將空閑分區劃分成一個6k和一個2k,然後把6k分配給程序,把2k的重新加入到空閑分區鏈。而快速適應演算法會直接把8k都分配給程序。文中說的不會產生內存碎片指的是外碎片,而那空餘的2k屬於內碎片。
❼ 分區存儲管理中常用哪些分配策略
1、固定分區存儲管理
其基本思想是將內存劃分成若干固定大小的分區,每個分區中最多隻能裝入一個作業。當作業申請內存時,系統按一定的演算法為其選擇一個適當的分區,並裝入內存運行。由於分區大小是事先固定的,因而可容納作業的大小受到限制,而且當用戶作業的地址空間小於分區的存儲空間時,造成存儲空間浪費。
一、空間的分配與回收
系統設置一張「分區分配表」來描述各分區的使用情況,登記的內容應包括:分區號、起始地址、長度和佔用標志。其中佔用標志為「0」時,表示目前該分區空閑;否則登記佔用作業名(或作業號)。有了「分區分配表」,空間分配與回收工作是比較簡單的。
二、地址轉換和存儲保護
固定分區管理可以採用靜態重定位方式進行地址映射。
為了實現存儲保護,處理器設置了一對「下限寄存器」和「上限寄存器」。當一個已經被裝入主存儲器的作業能夠得到處理器運行時,進程調度應記錄當前運行作業所在的分區號,且把該分區的下限地址和上限地址分別送入下限寄存器和上限寄存器中。處理器執行該作業的指令時必須核對其要訪問的絕對地址是否越界。
三、多作業隊列的固定分區管理
為避免小作業被分配到大的分區中造成空間的浪費,可採用多作業隊列的方法。即系統按分區數設置多個作業隊列,將作業按其大小排到不同的隊列中,一個隊列對應某一個分區,以提高內存利用率。
2、可變分區存儲管理
可變分區存儲管理不是預先將內存劃分分區,而是在作業裝入內存時建立分區,使分區的大小正好與作業要求的存儲空間相等。這種處理方式使內存分配有較大的靈活性,也提高了內存利用率。但是隨著對內存不斷地分配、釋放操作會引起存儲碎片的產生。
一、空間的分配與回收
採用可變分區存儲管理,系統中的分區個數與分區的大小都在不斷地變化,系統利用「空閑區表」來管理內存中的空閑分區,其中登記空閑區的起始地址、長度和狀態。當有作業要進入內存時,在「空閑區表」中查找狀態為「未分配」且長度大於或等於作業的空閑分區分配給作業,並做適當調整;當一個作業運行完成時,應將該作業佔用的空間作為空閑區歸還給系統。
可以採用首先適應演算法、最佳(優)適應演算法和最壞適應演算法三種分配策略之一進行內存分配。
二、地址轉換和存儲保護
可變分區存儲管理一般採用動態重定位的方式,為實現地址重定位和存儲保護,系統設置相應的硬體:基址/限長寄存器(或上界/下界寄存器)、加法器、比較線路等。
基址寄存器用來存放程序在內存的起始地址,限長寄存器用來存放程序的長度。處理機在執行時,用程序中的相對地址加上基址寄存器中的基地址,形成一個絕對地址,並將相對地址與限長寄存器進行計算比較,檢查是否發生地址越界。
三、存儲碎片與程序的移動
所謂碎片是指內存中出現的一些零散的小空閑區域。由於碎片都很小,無法再利用。如果內存中碎片很多,將會造成嚴重的存儲資源浪費。解決碎片的方法是移動所有的佔用區域,使所有的空閑區合並成一片連續區域,這一技術稱為移動技術(緊湊技術)。移動技術除了可解決碎片問題還使內存中的作業進行擴充。顯然,移動帶來系統開銷加大,並且當一個作業如果正與外設進行I/O時,該作業是無法移動的。
3、頁式存儲管理
基本原理
1.等分內存
頁式存儲管理將內存空間劃分成等長的若干區域,每個區域的大小一般取2的整數冪,稱為一個物理頁面有時稱為塊。內存的所有物理頁面從0開始編號,稱作物理頁號。
2.邏輯地址
系統將程序的邏輯空間按照同樣大小也劃分成若干頁面,稱為邏輯頁面也稱為頁。程序的各個邏輯頁面從0開始依次編號,稱作邏輯頁號或相對頁號。每個頁面內從0開始編址,稱為頁內地址。程序中的邏輯地址由兩部分組成:
邏輯地址
頁號p
頁內地址 d
3.內存分配
系統可用一張「位示圖」來登記內存中各塊的分配情況,存儲分配時以頁面(塊)為單位,並按程序的頁數多少進行分配。相鄰的頁面在內存中不一定相鄰,即分配給程序的內存塊之間不一定連續。
對程序地址空間的分頁是系統自動進行的,即對用戶是透明的。由於頁面尺寸為2的整數次冪,故相對地址中的高位部分即為頁號,低位部分為頁內地址。
3.5.2實現原理
1.頁表
系統為每個進程建立一張頁表,用於記錄進程邏輯頁面與內存物理頁面之間的對應關系。地址空間有多少頁,該頁表裡就登記多少行,且按邏輯頁的順序排列,形如:
邏輯頁號
主存塊號
0
B0
1
B1
2
B2
3
B3
2.地址映射過程
頁式存儲管理採用動態重定位,即在程序的執行過程中完成地址轉換。處理器每執行一條指令,就將指令中的邏輯地址(p,d)取來從中得到邏輯頁號(p),硬體機構按此頁號查頁表,得到內存的塊號B』,便形成絕對地址(B』,d),處理器即按此地址訪問主存。
3.頁面的共享與保護
當多個不同進程中需要有相同頁面信息時,可以在主存中只保留一個副本,只要讓這些進程各自的有關項中指向內存同一塊號即可。同時在頁表中設置相應的「存取許可權」,對不同進程的訪問許可權進行各種必要的限制。
4、段式存儲管理
基本原理
1.邏輯地址空間
程序按邏輯上有完整意義的段來劃分,稱為邏輯段。例如主程序、子程序、數據等都可各成一段。將一個程序的所有邏輯段從0開始編號,稱為段號。每一個邏輯段都是從0開始編址,稱為段內地址。
2.邏輯地址
程序中的邏輯地址由段號和段內地址(s,d)兩部分組成。
3.內存分配
系統不進行預先劃分,而是以段為單位進行內存分配,為每一個邏輯段分配一個連續的內存區(物理段)。邏輯上連續的段在內存不一定連續存放。
3.6.2實現方法
1.段表
系統為每個進程建立一張段表,用於記錄進程的邏輯段與內存物理段之間的對應關系,至少應包括邏輯段號、物理段首地址和該段長度三項內容。
2.建立空閑區表
系統中設立一張內存空閑區表,記錄內存中空閑區域情況,用於段的分配和回收內存。
3.地址映射過程
段式存儲管理採用動態重定位,處理器每執行一條指令,就將指令中的邏輯地址(s,d)取來從中得到邏輯段號(s),硬體機構按此段號查段表,得到該段在內存的首地址S』, 該段在內存的首地址S』加上段內地址d,便形成絕對地址(S』+d),處理器即按此地址訪問主存。
5、段頁式存儲管理
頁式存儲管理的特徵是等分內存,解決了碎片問題;段式存儲管理的特徵是邏輯分段,便於實現共享。為了保持頁式和段式上的優點,結合兩種存儲管理方案,形成了段頁式存儲管理。
段頁式存儲管理的基本思想是:把內存劃分為大小相等的頁面;將程序按其邏輯關系劃分為若干段;再按照頁面的大小,把每一段劃分成若干頁面。程序的邏輯地址由三部分組成,形式如下:
邏輯地址
段號s
頁號p
頁內地址d
內存是以頁為基本單位分配給每個程序的,在邏輯上相鄰的頁面內存不一定相鄰。
系統為每個進程建立一張段表,為進程的每一段各建立一張頁表。地址轉換過程,要經過查段表、頁表後才能得到最終的物理地址。