❶ 數據結構與演算法分析
本文出自:
www點54manong點com
請尊重原創,轉載請註明出處,謝謝!
什麼是數據結構,為什麼要學習數據結構?數據結構是否是一門純數學課程?它在專業課程體系中起什麼樣的作用?我們要怎麼才能學好數據結構?… 相信同學們在剛開始《數據結構》這門課的學習時,心裡有著類似前面幾個問題的這樣那樣的疑問。希望下面的內容能幫助大家消除疑惑,下定決心堅持學好這門課:
1 學習數據數據結構的意義
數據結構是計算機科學與技術專業、計算機信息管理與應用專業,電子商務等專業的基礎課,是十分重要的核心課程。所有的計算機系統軟體和應用軟體都要用到各種類型的數據結構。因此,要想更好地運用計算機來解決實際問題,僅掌握幾種計算機程序設計語言是難以應付當前眾多復雜的課題。要想有效地使用計算機、充分發揮計算機的性能,還必須學習和掌握好數據結構的有關知識。打好「數據結構」這門課程的扎實基礎,對於學習計算機專業的其他課程,如操作系統、資料庫管理系統、軟體工程、編譯原理、人工智慧、圖視學等都是十分有益的。
2 為什麼要學習數據結構
在計算機發展的初期,人們使用計算機的目的主要是處理數值計算問題。當我們使用計算機來解決一個具體問題時,一般需要經過下列幾個步驟:首先要從該具體問題抽象出一個適當的數學模型,然後設計或選擇一個解此數學模型的演算法,最後編出程序進行調試、測試,直至得到最終的解答。例如,求解梁架結構中應力的數學模型的線性方程組,可以使用迭代演算法來求解。
由於當時所涉及的運算對象是簡單的整型、實型或布爾類型數據,所以程序設計者的主要精力是集中於程序設計的技巧上,而無須重視數據結構。隨著計算機應用領域的擴大和軟、硬體的發展,非數值計算問題越來越顯得重要。據統計,當今處理非數值計算性問題佔用了85%以上的機器時間。這類問題涉及到的數據結構更為復雜,數據元素之間的相互關系一般無法用數學方程式加以描述。因此,解決這類問題的關鍵不再是數學分析和計算方法,而是要設計出合適的數據結構,才能有效地解決問題。下面所列舉的就是屬於這一類的具體問題。
例1:圖書館信息檢索系統。當我們根據書名查找某本書有關情況的時候;或者根據作者或某個出版社查找有關書籍的時候,或根據書刊號查找作者和出版社等有關情況的時候,只要我們建立了相關的數據結構,按照某種演算法編寫了相關程序,就可以實現計算機自動檢索。由此,可以在圖書館信息檢索系統中建立一張按書刊號順序排列的圖書信息表和分別按作者、書名、出版社順序排列的索引表,如圖1.1所示。由這四張表構成的文件便是圖書信息檢索的數學模型,計算機的主要操作便是按照某個特定要求(如給定書名)對圖書館藏書信息文件進行查詢。
諸如此類的還有學生信息查詢系統、商場商品管理系統、倉庫物資管理系統等。在這類文檔管理的數學模型中,計算機處理的對象之間通常存在著的是一種簡單的線性關系,這類數學模型可稱為線性的數據結構。
例2:八皇後問題。在八皇後問題中,處理過程不是根據某種確定的計演算法則,而是利用試探和回溯的探索技術求解。為了求得合理布局,在計算機中要存儲布局的當前狀態。從最初的布局狀態開始,一步步地進行試探,每試探一步形成一個新的狀態,整個試探過程形成了一棵隱含的狀態樹。如圖1.2所示(為了描述方便,將八皇後問題簡化為四皇後問題)。回溯法求解過程實質上就是一個遍歷狀態樹的過程。在這個問題中所出現的樹也是一種數據結構,它可以應用在許多非數值計算的問題中。
例3:教學計劃編排問題。一個教學計劃包含許多課程,在教學計劃包含的許多課程之間,有些必須按規定的先後次序進行,有些則沒有次序要求。即有些課程之間有先修和後續的關系,有些課程可以任意安排次序。這種各個課程之間的次序關系可用一個稱作圖的數據結構來表示,如圖1.3所示。有向圖中的每個頂點表示一門課程,如果從頂點vi到vj之間存在有向邊<vi,vj>,則表示課程i必須先於課程j進行。由以上三個例子可見,描述這類非數值計算問題的數學模型不再是數學方程,而是諸如線性表、樹、圖之類的數據結構。因此,可以說數據結構課程主要是研究非數值計算的程序設計問題中所出現的計算機操作對象以及它們之間的關系和操作的學科。
學習數據結構的目的是為了了解計算機處理對象的特性,將實際問題中所涉及的處理對象在計算機中表示出來並對它們進行處理。與此同時,通過演算法訓練來提高學生的思維能力,通過程序設計的技能訓練來促進學生的綜合應用能力和專業素質的提高。
3數據結構課程的內容
數據結構與數學、計算機硬體和軟體有十分密切的關系,它是介於數學、計算機硬體和計算機軟體之間的一門計算機專業的核心課程,是高級程序設計語言、操作系統、編譯原理、資料庫、人工智慧、圖視學等課程的基礎。同時,數據結構技術也廣泛應用於信息科學、系統工程、應用數學以及各種工程技術領域。
數據結構課程重在討論軟體開發過程中的方案設計階段、同時設計編碼和分析階段的若干基本問題。此外,為了構造出好的數據結構及其實現,還需考慮數據結構及其實現的評價與選擇。因此,數據結構的內容包括三個層次的五個「要素」,如圖1.3所示。
數據結構的核心技術是分解與抽象。通過分解可以劃分出數據的三個層次;再通過抽象,舍棄數據元素的具體內容,就得到邏輯結構。類似地,通過分解將處理要求劃分成各種功能,再通過抽象舍棄實現細節,就得到運算的定義。上述兩個方面的結合使我們將問題變換為數據結構。這是一個從具體(即具體問題)到抽象(即數據結構)的過程。然後,通過增加對實現細節的考慮進一步得到存儲結構和實現運算,從而完成設計任務。這是一個從抽象(即數據結構)到具體(即具體實現)的過程。熟練地掌握這兩個過程是數據結構課程在專業技能培養方面的基本目標。
結束語:數據結構作為一門獨立的課程在國外是從1968年才開始的,但在此之前其有關內容已散見於編譯原理及操作系統之中。20世紀60年代中期,美國的一些大學開始設立有關課程,但當時的課程名稱並不叫數據結構。1968年美國唐.歐.克努特教授開創了數據結構的最初體系,他所著的《計算機程序設計技巧》第一卷《基本演算法》是第一本較系統地闡述數據的邏輯結構和存儲結構及其操作的著作。從20世紀60年代末到70年代初,出現了大型程序,軟體也相對獨立,結構程序設計成為程序設計方法學的主要內容,人們越來越重視數據結構。從70年代中期到80年代,各種版本的數據結構著作相繼出現。目前,數據結構的發展並未終結,一方面,面向各專門領域中特殊問題的數據結構得到研究和發展,如多維圖形數據結構等;另一方面,從抽象數據類型和面向對象的觀點來討論數據結構已成為一種新的趨勢,越來越被人們所重視。
❷ 操作系統(四)文件管理
文件—就是一組有意義的信息/數據集合
文件屬於抽象數據類型。為了恰當地定義文件,需要考慮有關文件的操作。操作系統提供系統調用,它對文件進行創建、寫、讀、重定位、搠除和截斷等操作。
所謂的「邏輯結構」,就是指在用戶看來,文件內部的數據應該是如何組織起來的。而「物理結構」指的是在操作系統看來,文件的數據是如何存放在外存中的。
無結構文件:文件內部的數據就是一系列二進制流或字元流組成。又稱「流式文件」
文件內部的數據其實就是一系列字元流,沒有明顯的結構特性。因此也不用探討無結構文件的「邏輯結構」問題。
有結構文件:由一組相似的記錄組成,又稱「記錄式文件」。每條記錄又若干個數據項組成。 [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表上標明。(在這種方式中,壞塊對操作系統不透明)。
對於復雜的磁碟,磁碟控制器(磁碟設備內部的一個硬體部件)會維護一個壞塊鏈表。在磁碟出廠前進行低級格式化(物理格式化)時就將壞塊鏈進行初始化。會保留一些「備用扇區」,用於替換壞塊。這種方案稱為扇區備用。且這種處理方式中,壞塊對操作系統透明
❸ 一道很難的演算法題
只想到一種暴力方法,就是找到一個最短的+串進行枚舉所有的匹配可能,由於長度最多是8,2^8不是很大還可以接受.然後對所有的+串進行一次改進,每當發現一個匹配串不符合某個+串,則進行添加,若無論如何都無法匹配,則否決.然後再對所有的-串進行一次檢查,若匹配則否決,最後剩下的匹配串裡面輸出最短那個.
時間復雜度在O(2^m*n*m)級別,還算在接受范圍之內.
不過的確不優美,最好是能找到更優的做法.
❹ 王者榮耀:系統怎麼操作給我匹配這么多神坑隊友,懂了
因為有大把的游戲玩家可以匹配到一起,就是很多幾千場的高手玩家經常會遇到幾十場甚至幾場的菜鳥玩家,他們也許是因為你的出色發揮而獲得勝利,也許是因為你的故意送分而崩盤,如果你玩的很差,不厲害,有一個很重要的東西叫matchmaking ranking(比賽匹配分級),以此尋找存在感
在眾多玩家的一致呼喚下,MMR匹配分級系統應運而生
MMR匹配系統,會一直連勝過連敗,直到MMR平衡至接近於0
這看上去很公平。但是問題是,當你一直連勝或連敗後。這是一套成熟的,對手的MMR增加,你輸了對手的MMR減少。當你的MMR達到一個極值,導致一邊倒的碾壓和屠殺。就是因為平衡被打破所造成的,玩家之間叢段含對局的匹配方式主要有兩種:隨機匹配和等級場次匹配。漸漸的人們發現按照隨機的匹配方式對玩家進行分級來匹配會有一個弊端,也許是20,這將會打破平衡。也許是11。
但是這種靠系統強制干預玩家勝敗的機制對於一些職業玩家和高手玩家來說簡直是糟透了,也有無數大神親測證實,至於原因要先講解一下MMR(比賽匹配分級系統)
在競技類游戲剛剛進入市場時王者連勝必連敗,這對一些新手玩家會造成極差的游戲體驗。至於另一種匹配模式按照等級和對戰場次來匹配對手雖然避免了之前的問題,但是新的問題再次出現,死的也多,那麼坑爹選手就出現了,就像鍾擺一樣,他總是希望回到它與地平線垂直的位置,MMR=0這個位置。
這滲笑樣的匹配機制改善了玩家對局中的游戲體驗,道理是一樣的!
匹配系統—50%的平衡(勝率控制)
過於嚴苛的匹配計算方式會導致匹配等待時間的延長,也許是12,公正,平衡的匹配系統。
首先,反過來,那你匹配到的對手將會高於這個值,它有一個值初始為0 。
當你進燃羨行比賽的時候,每贏一場MMR+1,每輸一場MMR-1
當你贏得越多,你的MMR越高,那你將面對的挑戰也就越強,就是一些擁有幾千場對戰經驗的高手會故意練小號,在低端局大殺特殺,大神分分鍾登榜,你就有很大概率去坑這個強的玩家,匹配系統中,不同於一般的匹配,也不同於等級限制匹配,系統會把你和比較強的選手匹配在一起,這是許多玩家公認的,如果很低,那系統判斷你弱,系統會把強的玩家和弱的玩家匹配在一起,根據你的擊殺/死亡率、參團率輸出比等等計算出一個綜合分數,如果這個數值很高。你贏了,但是也維持一個相對的平衡,50%的平衡。從而保證了用戶粘性。
那麼很多人就會有疑問了,那系統會判斷你是強,簡稱MMR,那麼就造成了後面比賽的平衡將會打破,你的隊友MMR也會變化,對手的MMR指數將會比你的高,相反的,如果你的MMR很低,那你匹配到的對手的MMR也將會很低,比如你的MMR為10,所以系統會允許差別在一定數值之內的玩家匹配到一起,那尋找游戲的速度將會加快,不會讓大神覺得游戲索然無味也不會讓菜鳥新手覺得游戲玩不下去,菜鳥分分鍾輸到退游,毫無趣味性可言,為什麼有時候你會遇到3-4個比你菜的隊友,或者是你遇到了3-4個比你厲害很多的隊友,在連勝-連敗中不斷循環,系統怎麼判斷玩家的強弱程度呢?
其實除了MMR,系統還有一個內置數據,多數對局往往是一邊倒的碾壓和一邊倒的被碾壓,想要快速達到符合自己的段位往往需要超越此段位幾倍的技術和意識,否則在此機制的干預下
❺ 操作系統第四章【2】內存空間管理---連續
內存分為系統區和用戶區兩部分:
系統區:僅提供給OS使用,通常放在內存低址部分
用戶區:除系統區以外的全部內存空間,提供給用戶使用。
最簡單的一種存儲管理方式,只能用於單用戶、單任務的操作系統中。
優點:易於管理。
缺點:對要求內存空間少的程序,造成內存浪費;程序全部裝入,很少使用的程序部分也佔用內存。
把內存分為一些大小相等或不等的分區(partition),每個應用進程佔用一個分區。操作系統佔用其中一個分區。
u提高:支持多個程序並發執行,適用於多道程序系統和分時系統。最早的多道程序存儲管理方式。
劃分為幾個分區,便只允許幾道作業並發
1如何劃分分區大小:
n分區大小相等:只適合於多個相同程序的並發執行(處理多個類型相同的對象)。缺乏靈活性。
n分區大小不等:多個小分區、適量的中等分區、少量的大分區。根據程序的大小,分配當前空閑的、適當大小的分區。
2需要的數據結構
建立一記錄相關信息的分區表(或分區鏈表),表項有: 起始位置 大小 狀態
分區表中,表項值隨著內存的分配和釋放而動態改變
3程序分配內存的過程:
也可將分區表分為兩個表格:空閑分區表/佔用分區表。從而減小每個表格長度。
檢索演算法:空閑分區表可能按不同分配演算法採用不同方式對表項排序(將分區按大小排隊或按分區地址高低排序)。
過程:檢索空閑分區表;找出一個滿足要求且尚未分配的分區,分配給請求程序;若未找到大小足夠的分區,則拒絕為該用戶程序分配內存。
固定分配的不足:
內碎片(一個分區內的剩餘空間)造成浪費
分區總數固定,限制並發執行的程序數目。
(3)動態分區分配
分區的大小不固定:在裝入程序時根據進程實際需要,動態分配內存空間,即——需要多少劃分多少。
空閑分區表項:從1項到n項:
內存會從初始的一個大分區不斷被劃分、回收從而形成內存中的多個分區。
動態分區分配
優點:並發進程數沒有固定數的限制,不產生內碎片。
缺點:有外碎片(分區間無法利用的空間)
1)數據結構
①空閑分區表:
•記錄每個空閑分區的情況。
•每個空閑分區對應一個表目,包括分區序號、分區始址及分區的大小等數據項。
②空閑分區鏈:
•每個分區的起始部分,設置用於控制分區分配的信息,及用於鏈接各分區的前向指針;
•分區尾部則設置一後向指針,在分區末尾重復設置狀態位和分區大小表目方便檢索。
2)分區分配演算法
動態分區方式,分區多、大小差異各不相同,此時把一個新作業裝入內存,更需選擇一個合適的分配演算法,從空閑分區表/鏈中選出一合適分區
①首次適應演算法FF
②循環首次適應演算法
③最佳適應演算法
④最差適應演算法
⑤快速適應演算法
①首次適應演算法FF(first-fit)
1.空閑分區排序:以地址遞增的次序鏈接。
2.檢索:分配內存時,從鏈首開始順序查找直至找到一個大小能滿足要求的空閑分區;
3.分配:從該分區中劃出一塊作業要求大小的內存空間分配給請求者,餘下的空閑分區大小改變仍留在空閑鏈中。
u若從頭到尾檢索不到滿足要求的分區則分配失敗
優點:優先利用內存低址部分,保留了高地址部分的大空閑區;
缺點:但低址部分不斷劃分,會產生較多小碎片;而且每次查找從低址部分開始,會逐漸增加查找開銷。
②循環首次適應演算法(next-fit)
1.空閑分區排序:按地址
2.檢索:從上次找到的空閑分區的下一個空閑分區開始查找,直到找到一個能滿足要求的空閑分區。為實現演算法,需要:
©設置一個起始查尋指針
©採用循環查找方式
3.分配:分出需要的大小
優點:空閑分區分布均勻,減少查找開銷
缺點:缺乏大的空閑分區
③最佳適應演算法 (best-fit)
總是把能滿足要求、又是最小的空閑分區分配給作業,避免「大材小用」。
1.空閑分區排序:所有空閑分區按容量從小到大排序成空閑分區表或鏈。
2.檢索:從表或鏈的頭開始,找到的第一個滿足的就分配
3.分配:分出需要的大小
缺點:每次找到最合適大小的分區割下的空閑區也總是最小,會產生許多難以利用的小空閑區(外碎片)
④最差適應演算法/最壞匹配法(worst-fit): 基本不留下小空閑分區,但會出現缺乏較大的空閑分區的情況。
⑤快速適應演算法
n根據進程常用空間大小進行劃分,相同大小的串成一個鏈,需管理多個各種不同大小的分區的鏈表。進程需要時,從最接近大小需求的鏈中摘一個分區。類似的:夥伴演算法
n能快速找到合適分區,但鏈表信息會很多;實際上是空間換時間。
3)分區分配操作
分配內存
找到滿足需要的合適分區,劃出進程需要的空間
s<=size,將整個分區分配給請求者
s> size,按請求的大小劃出一塊內存空間分配出去,餘下部分留在空閑鏈中,將分配區首址返回給調用者。
回收內存
進程運行完畢釋放內存時,系統根據回收區首址a,在空閑分區鏈(表)中找到相應插入點,根據情況修改空閑分區信息,可能會進行空閑分區的合並:
(4)動態重定位分區分配
——有緊湊功能的動態分區分配
用戶程序在內存中移動,將空閑空間緊湊起來提高空間利用率。但必然需要地址變化,增加「重定位」工作。
(5)內存空間管理之對換
當內存空間還是滿足不了需求時,引入「對換」思想:
把內存中暫時不能運行、或暫時不用的程序和數據調到外存上,以騰出足夠的內存;把已具備運行條件的進程和進程所需要的程序和數據,調入內存。
u按對換單位分類:
Ø整體對換(或進程對換):以整個進程為單位(連續分配)
Ø頁面對換或分段對換:以頁或段為單位(離散分配)
❻ Linux內存系統
維基網路——虛擬內存定義
All about Linux swap space
Linux將物理RAM (Random Access Memory) 劃分為稱為頁面的內存塊。交換是將一頁內存復制到硬碟上的預配置空間(稱為交換空間)以釋放改內存頁面上的過程。物理內存和交換空間的組合就是可用的虛擬內存量。
虛擬內存的那點事兒
進程是與其他進程共享CPU和內存資源的。為了有效的管理內存並減少出錯,現代操作系統提供了一種對主存的抽象概念,即:虛擬內存( Virtual Memory )。 虛擬內存為每個進程提供一個一致的,私有的地址空間,每個進程擁有一片連續完整的內存空間。
正如 維基網路 所說,虛擬內存不只是「使用硬碟空間來擴展內存」的技術。 虛擬內存的重要意義是它定義了一個連續的虛擬地址空間, 使得程序編寫難度降低。並且, 把內存擴展到硬碟空間只是使用虛擬內存的必然結果,虛擬內存空間會存在硬碟中,並且會被全部放入內存中緩沖(按需),有的操作系統還會在內存不夠的情況下,將一進程的內存全部放入硬碟空間中,並在切換到進程時再從硬碟讀取 (這也是Windows會經常假死的原因...)。
虛擬內存主要提供了如下三個重要的能力:
內存通常被組織為一個由M個連續的位元組大小的單元組成的數組。每個位元組都有一個唯一的物理地址 (Physical Address PA) ,作為到數組的索引。
CPU訪問內存最簡單直接的方法就是使用物理地址,這種定址方式稱為 物理定址 。
現代計算機使用的是一種被稱為虛擬定址 (Virtual Addressing) 的定址方式。 使用虛擬定址,CPU需要將虛擬地址翻譯成物理地址,這樣才能訪問到真實的物理內存。
虛擬定址需要硬體與操作系統之間相互合作。 CPU中含有一個被稱為內存管理單元 (Memory Management Unit,MMU) 的硬體,它的功能是將虛擬地址轉換稱為物理地址,MMU需要藉助存放在內存中的 頁表 來動態翻譯虛擬地址,該頁表由操作系統管理。
分頁表是一種數據結構,它用於計算機操作系統中虛擬內存系統,其存儲了虛擬地址到物理地址之間的映射。虛擬地址在訪問進程中是唯一的,而物理地址在硬體(比如內存)中是唯一的。
在操作系統中使用 虛擬內存 ,每個進程會認為使用一塊大的連續的內存,事實上,每個進程的內存散布在 物理內存 的不同區域。或者可能被調出到備份存儲中(一般是硬碟)。當一個進程請求自己的內存,操作系統負責把程序生成的虛擬地址,映射到實際存儲的物理內存上。操作系統在 分頁表 中存儲虛擬地址到物理地址的映射。每個映射被稱為 分頁表項(page table entry ,PTE) 。
在一個簡單的地址空間方案中,由虛擬地址定址的頁與物理內存中的幀之間的關系。物理內存可以包含屬於許多進程的頁。如果不經常使用,或者物理內存已滿,可以將頁面分頁到磁碟。在上圖中,並非所有頁面都在物理內存中。
虛擬地址到物理地址的轉換(即虛擬內存的管理)、內存保護、CPU高速緩存的控制。
現代的內存管理單元是以 頁 的方式,分割虛擬地址空間(處理器使用的地址范圍)的;頁的大小是2的n次方,通常為幾KB(位元組)。地址尾部的n位(頁大小的2的次方數)作為頁內的偏移量保持不變。其餘的地址位(address)為(虛擬)頁號。
內存管理單元通常藉助一種叫做轉譯旁觀緩沖器(Translation Lookaside Buffer,TLB)和相聯高速緩存來將虛擬頁號轉換為物理頁號。當後備緩沖器中沒有轉換記錄時,則使用一種較慢的機制,其中包括專用硬體的數據結構或軟體輔助手段。這個數據結構稱為 分頁表 ,頁表中的數據叫做 分頁表項 (page table entry PTE)。物理頁號結合頁偏移量便提供了完整的物理地址。
頁表 或 轉換後備緩沖器數據項應該包括的信息有:
有時候,TLB和PTE會 禁止對虛擬頁訪問 ,這可能是因為沒有RAM與虛擬頁相關聯。如果是這種情況,MMU將向CPU發出頁錯誤的信號,操作系統將進行處理,也許會尋找RAM的空白幀,同時建立一個新的PTE將之映射到所請求的虛擬地址。如果沒有空閑的RAM,可能必須關閉一個已經存在的頁面,使用一些替換演算法,將之保存到磁碟中(這被稱為頁面調度)。
當需要將虛擬地址轉換為物理地址時,首先搜索TLB,如果找到匹配(TLB)命中,則返回物理地址並繼續存儲器訪問。然而,如果沒有匹配(稱為TLB未命中),則MMU或操作系統TLB未命中處理器通常會查找 頁表 中的地址映射以查看是否存在映射(頁面遍歷),如果存在,則將其寫回TLB(這必須完成,因為硬體通過虛擬存儲器系統中的TLB訪問存儲器),並且重啟錯誤指令(這也可以並行發生)。此後續轉換找到TLB命中,並且內存訪問將繼續。
虛擬地址到物理地址的轉換過程,如果虛擬內存不存在與TLB,轉換會被重置並通過分頁表和硬體尋找。
通常情況下,用於處理此中斷的程序是操作系統的一部分。如果操作系統判斷此次訪問有效,那麼 操作系統會嘗試將相關的分頁從硬碟上的虛擬內存文件調入內存。 而如果訪問是不被允許的,那麼操作系統通常會結束相關的進程。
雖然叫做「頁缺失」錯誤,但實際上這並不一定是一種錯誤。而且這一機制是利用虛擬內存來增加程序可用內存空間。
發生這種情況的可能性:
當原程序再次需要該頁內的數據時,如果這一頁確實沒有被分配出去,那麼系統只需要重新為該頁在MMU內注冊映射即可。
操作系統需要:
硬性頁缺失導致的性能損失是很大的。
另外,有些操作系統會將程序的一部分延遲到需要使用的時候再載入入內存執行,以此提升性能。這一特性也是通過捕獲硬性頁缺失達到的。
當硬性頁缺失過於頻繁發生時,稱發生 系統顛簸。
具體動作與所使用的操作系統有關,比如Windows會使用異常機制向程序報告,而類Unix系統則使用信號機制。
盡管在整個運行過程中,程序引用不同的頁面總數(也就是虛擬內存大小)可能超出了物理存儲器(DRAM)總大小,但是程序常常在較小的活動頁面上活動,這個集合叫做工作集或者常駐集。在工作集被緩存後,對它的反復調用會使程序命中提高,從而提高性能。
大部分的程序都可以在存儲器獲取數據和讀取中達到穩定的狀態,當程序達到穩定狀態時,存儲器的使用量通常都不會太大。虛擬內存雖然可以有效率控制存儲器的使用, 但是大量的頁缺失還是造成了系統遲緩的主要因素。 當工作集的大小超過物理存儲器大小,程序將會發生一種不幸的情況,這種情況稱為 「顛簸」 ,頁面將不停的寫入、釋放、讀取,由於大量的丟失(而非命中)而損失極大性能。用戶可以增加隨機存取存儲器的大小或是減少同時在系統里運行程序的數量來降低系統顛簸的記錄。
推薦閱讀:
操作系統--分頁(一)
操作系統實現(二):分頁和物理內存管理