作業系統學習總結(超讚!!!)
我是技術搬運工,好東西當然要和大家分享啦.原文地址
作業系統基本特徵
1. 併發
併發性是指巨集觀上在一段時間內能同時執行多個程式,而並行性則指同一時刻能執行多個指令。
並行需要硬體支援,如多流水線或者多處理器。
作業系統通過引入程序和執行緒,使得程式能夠併發執行。
2. 共享
共享是指系統中的資源可以供多個併發的程序共同使用。
有兩種共享方式:互斥共享和同時共享。
互斥共享的資源稱為臨界資源,例如印表機等,在同一時間只允許一個程序訪問,否則會出現錯誤,需要用同步機制來實現對臨界資源的訪問。
3. 虛擬
虛擬技術把一個物理實體轉換為多個邏輯實體。主要有兩種虛擬技術:時分複用技術和空分複用技術,例如多個程序能在同一個處理器上併發執行使用了時分複用技術,讓每個程序輪流佔有處理器,每次只執行一小個時間片並快速切換,這樣就好像有多個處理器進行處理。
4. 非同步
非同步是指程序不是一次性執行完畢,而是走走停停,以不可知的速度向前推進。
系統呼叫
如果一個程序在使用者態需要用到作業系統的一些功能,就需要使用系統呼叫從而陷入核心,由作業系統代為完成。
可以由系統呼叫請求的功能有裝置管理、檔案管理、程序管理、程序通訊、儲存器管理等。
中斷分類
1. 外中斷
由 CPU 執行指令以外的事件引起,如 I/O 結束中斷,表示裝置輸入/輸出處理已經完成,處理器能夠傳送下一個輸入/輸出請求。此外還有時鐘中斷、控制檯中斷等。
2. 異常
由 CPU 執行指令的內部事件引起,如非法操作碼、地址越界、算術溢位等。
3. 陷入
在使用者程式中使用系統呼叫。
大核心和微核心
1. 大核心
大核心是將作業系統功能作為一個緊密結合的整體放到核心,由於各模組共享資訊,因此有很高的效能。
2. 微核心
由於作業系統不斷複雜,因此將一部分作業系統功能移出核心,從而降低核心的複雜性。移出的部分根據分層的原則劃分成若干服務,相互獨立。但是需要頻繁地在使用者態和核心態之間進行切換,會有一定的效能損失。
第二章 程序管理
程序與執行緒
1. 程序
程序是作業系統進行資源分配的基本單位。
程序控制塊 (Process Control Block, PCB) 描述程序的基本資訊和執行狀態,所謂的建立程序和撤銷程序,都是指對 PCB 的操作。
2. 執行緒
一個執行緒中可以有多個執行緒,是獨立排程的基本單位。同一個程序中的多個執行緒之間可以併發執行,它們共享程序資源。
3. 區別
① 擁有資源:程序是資源分配的基本單位,但是執行緒不擁有資源,執行緒可以訪問率屬程序的資源。
② 排程:執行緒是獨立排程的基本單位,在同一程序中,執行緒的切換不會引起程序切換,從一個程序內的執行緒切換到另一個程序中的執行緒時,會引起程序切換。
③ 系統開銷:由於建立或撤銷程序時,系統都要為之分配或回收資源,如記憶體空間、I/O 裝置等,因此作業系統所付出的開銷遠大於建立或撤銷執行緒時的開銷。類似地,在進行程序切換時,涉及當前執行程序 CPU 環境的儲存及新排程程序 CPU 環境的設定。而執行緒切換時只需儲存和設定少量暫存器內容,開銷很小。此外,由於同一程序內的多個執行緒共享程序的地址空間,因此,這些執行緒之間的同步與通訊非常容易實現,甚至無需作業系統的干預。
④ 通訊方面:程序間通訊 (IPC) 需要程序同步和互斥手段的輔助,以保證資料的一致性,而執行緒間可以通過直接讀/寫程序資料段(如全域性變數)來進行通訊。
舉例:QQ 和 瀏覽器是兩個程序,瀏覽器程序裡面有很多執行緒,例如 http 請求執行緒、事件響應執行緒、渲染執行緒等等,執行緒的併發執行使得在瀏覽器中點選一個新連結從而發起 http 請求時,瀏覽器還可以響應使用者的其它事件。
程序狀態的切換
阻塞狀態是缺少需要的資源從而由執行狀態轉換而來,但是該資源不包括 CPU,缺少 CPU 會讓程序從執行態轉換為就緒態。
只有就緒態和執行態可以相互轉換,其它的都是單向轉換。就緒狀態的程序通過排程演算法從而獲得 CPU 時間,轉為執行狀態;而執行狀態的程序,在分配給它的 CPU 時間片用完之後就會轉為就緒狀態,等待下一次排程。
排程演算法
需要針對不同環境來討論排程演算法。
1. 批處理系統中的排程
1.1 先來先服務(FCFS)
first-come first-serverd。
排程最先進入就緒佇列的作業。
有利於長作業,但不利於短作業,因為短作業必須一直等待前面的長作業執行完畢才能執行,而長作業又需要執行很長時間,造成了短作業等待時間過長。
1.2 短作業優先(SJF)
shortest job first。
排程估計執行時間最短的作業。
長作業有可能會餓死,處於一直等待短作業執行完畢的狀態。如果一直有短作業到來,那麼長作業永遠得不到排程。
1.3 最短剩餘時間優先(SRTN)
shortest remaining time next。
2. 互動式系統中的排程
2.1 優先權優先
除了可以手動賦予優先權之外,還可以把響應比作為優先權,這種排程方式叫做高響應比優先排程演算法。
響應比 = (等待時間 + 要求服務時間) / 要求服務時間 = 響應時間 / 要求服務時間
這種排程演算法主要是為了解決 SJF 中長作業可能會餓死的問題,因為隨著等待時間的增長,響應比也會越來越高。
2.2 時間片輪轉
將所有就緒程序按 FCFS 的原則排成一個佇列,每次排程時,把 CPU 分配給隊首程序,該程序可以執行一個時間片。當時間片用完時,由計時器發出時鐘中斷,排程程式便停止該程序的執行,並將它送往就緒佇列的末尾,同時繼續把 CPU 分配給隊首的程序。
時間片輪轉演算法的效率和時間片有很大關係。因為每次程序切換都要儲存程序的資訊並且載入新程序的資訊,如果時間片太短,程序切換太頻繁,在程序切換上就會花過多時間。
2.3 多級反饋佇列
① 設定多個就緒佇列,併為各個佇列賦予不同的優先順序。第一個佇列的優先順序最高,第二個佇列次之,其餘各佇列的優先權逐個降低。該演算法賦予各個佇列中程序執行時間片的大小也各不相同,在優先權越高的佇列中,為每個程序所規定的執行時間片就越小。
② 當一個新程序進入記憶體後,首先將它放入第一佇列的末尾,按 FCFS 原則排隊等待排程。當輪到該程序執行時,如它能在該時間片內完成,便可準備撤離系統;如果它在一個時間片結束時尚未完成,排程程式便將該程序轉入下一個佇列的隊尾。
③ 僅當前 i -1 個佇列均空時,才會排程第 i 佇列中的程序執行。
優點:實時性好,也適合執行短作業和長作業。
2.4 短程序優先
3. 實時系統中的排程
實時系統要一個服務請求在一個確定時間內得到響應。
分為硬實時和軟實時,前者必須滿足絕對的截止時間,後者可以容忍一定的超時。
程序同步
1. 臨界區
對臨界資源進行訪問的那段程式碼稱為臨界區。
為了互斥訪問臨界資源,每個程序在進入臨界區之前,需要先進行檢查。
// entry section // critical section; // exit section
2. 同步與互斥
同步指多個程序按一定順序執行;互斥指多個程序在同一時刻只有一個程序能進入臨界區。
同步是在對臨界區互斥訪問的基礎上,通過其它機制來實現有序訪問的。
3. 訊號量
**訊號量(Samaphore)**是一個整型變數,可以對其執行 down 和 up 操作,也就是常見的 P 和 V 操作。
- down : 如果訊號量大於 0 ,執行 - 1 操作;如果訊號量等於 0,將程序睡眠,等待訊號量大於 0;
- up:對訊號量執行 + 1 操作,並且喚醒睡眠的程序,讓程序完成 down 操作。
down 和 up 操作需要被設計成原語,不可分割,通常的做法是在執行這些操作的時候遮蔽中斷。
如果訊號量的取值只能為 0 或者 1,那麼就成為了互斥量(Mutex),0 表示臨界區已經加鎖,1 表示臨界區解鎖。
typedef int samaphore; samaphore mutex = 1; void P1() { down(mutex); // 臨界區 up(mutex); } void P2() { down(mutex); // 臨界區 up(mutex); }
使用訊號量實現生產者-消費者問題
使用一個互斥量 mutex 來對臨界資源進行訪問;empty 記錄空緩衝區的數量,full 記錄滿緩衝區的數量。
注意,必須先執行 down 操作再用互斥量對臨界區加鎖,否則會出現死鎖。如果都先對臨界區加鎖,然後再執行 down 操作,考慮這種情況:生產者對臨界區加鎖後,執行 down(empty) 操作,發現 empty = 0,此時生成者睡眠。消費者此時不能進入臨界區,因為生產者對臨界區加鎖了,也就無法對執行 up(empty) 操作,那麼生產者和消費者就會一直等待下去。
#define N 100 typedef int samaphore; samaphore mutex = 1; samaphore empty = N; samaphore full = 0; void producer() { while(TRUE){ int item = produce_item; down(empty); down(mutex); insert_item(item); up(mutex); up(full); } } void consumer() { while(TRUE){ down(full); down(mutex); int item = remove_item(item); up(mutex); up(empty); consume_item(item); } }
4. 管程
使用訊號量機制實現的生產者消費者問題需要客戶端程式碼做很多控制,而管程把控制的程式碼獨立出來,不僅不容易出錯,也使得客戶端程式碼呼叫更容易。
c 語言不支援管程,下面的示例程式碼使用了類 Pascal 語言來描述管程。示例程式碼中的管程提供了 insert() 和 remove() 方法,客戶端程式碼通過呼叫這兩個方法來解決生產者-消費者問題。
monitor ProducerConsumer integer i; condition c; procedure insert(); begin end; procedure remove(); begin end; end monitor;
管程有一個重要特性:在一個時刻只能有一個程序使用管程。程序在無法繼續執行的時候不能一直佔用管程,必須將程序阻塞,否者其它程序永遠不能使用管程。
管程引入了 條件變數 以及相關的操作:wait() 和 signal() 來實現同步操作。對條件變數執行 wait() 操作會導致呼叫程序阻塞,把管程讓出來讓另一個程序持有。signal() 操作用於喚醒被阻塞的程序。
使用管程實現生成者-消費者問題
monitor ProducerConsumer condition full, empty; integer count := 0; condition c; procedure insert(item: integer); begin if count = N then wait(full); insert_item(item); count := count + 1; if count = 1 ten signal(empty); end; function remove: integer; begin if count = 0 then wait(empty); remove = remove_item; count := count - 1; if count = N -1 then signal(full); end; end monitor; procedure producer begin while true do begin item = produce_item; ProducerConsumer.insert(item); end end; procedure consumer begin while true do begin item = ProducerConsumer.remove; consume_item(item); end end;
程序通訊
程序通訊可以看成是不同程序間的執行緒通訊,對於同一個程序內執行緒的通訊方式,主要使用訊號量、條件變數等同步機制。
1. 管道
管道是單向的、先進先出的、無結構的、固定大小的位元組流,它把一個程序的標準輸出和另一個程序的標準輸入連線在一起。寫程序在管道的尾端寫入資料,讀程序在管道的首端讀出資料。資料讀出後將從管道中移走,其它讀程序都不能再讀到這些資料。
管道提供了簡單的流控制機制,程序試圖讀空管道時,在有資料寫入管道前,程序將一直阻塞。同樣地,管道已經滿時,程序再試圖寫管道,在其它程序從管道中移走資料之前,寫程序將一直阻塞。
Linux 中管道是通過空檔案來實現。
管道有三種:
① 普通管道:有兩個限制:一是隻支援半雙工通訊方式,即只能單向傳輸;二是隻能在父子程序之間使用;
② 流管道:去除第一個限制,支援雙向傳輸;
③ 命名管道:去除第二個限制,可以在不相關程序之間進行通訊。
2. 訊號量
訊號量是一個計數器,可以用來控制多個程序對共享資源的訪問。它常作為一種鎖機制,防止某程序正在訪問共享資源時,其它程序也訪問該資源。因此,主要作為程序間以及同一程序內不同執行緒之間的同步手段。
3. 訊息佇列
訊息佇列克服了訊號傳遞資訊少、管道只能承載無格式位元組流以及緩衝區大小受限等缺點。
4. 訊號
訊號是一種比較複雜的通訊方式,用於通知接收程序某個事件已經發生。
5. 共享記憶體
共享記憶體就是對映一段能被其它程序所訪問的記憶體,這段共享記憶體由一個程序建立,但多個程序都可以訪問。共享記憶體是最快的 IPC 方式,它是針對其它程序間通訊方式執行效率低而專門設計的。它往往與其它通訊機制(如訊號量)配合使用,來實現程序間的同步和通訊。
6. 套接字
套接字也是一種程序間通訊機制,與其它通訊機制不同的是,它可用於不同機器間的程序通訊。
經典同步問題
生產者和消費者問題前面已經討論過。
1. 讀者-寫者問題
允許多個程序同時對資料進行讀操作,但是不允許讀和寫以及寫和寫操作同時發生。
一個整型變數 count 記錄在對資料進行讀操作的程序數量,一個互斥量 count_mutex 用於對 count 加鎖,一個互斥量 data_mutex 用於對讀寫的資料加鎖。
typedef int semaphore; semaphore count_mutex = 1; semaphore data_mutex = 1; int count = 0; void reader() { while(TRUE) { down(count_mutex); count++; if(count == 1) down(data_mutex); // 第一個讀者需要對資料進行加鎖,防止寫程序訪問 up(count_mutex); read(); down(count_mutex); count--; if(count == 0) up(data_mutex); up(count_mutex); } } void writer() { while(TRUE) { down(data_mutex); write(); up(data_mutex); } }
2. 哲學家進餐問題
五個哲學家圍著一張圓周,每個哲學家面前放著飯。哲學家的生活有兩種交替活動:吃飯以及思考。當一個哲學家吃飯時,需要先一根一根拿起左右兩邊的筷子。
下面是一種錯誤的解法,考慮到如果每個哲學家同時拿起左手邊的筷子,那麼就無法拿起右手邊的筷子,造成死鎖。
#define N 5 #define LEFT (i + N - 1) % N #define RIGHT (i + N) % N typedef int semaphore; semaphore chopstick[N]; void philosopher(int i) { while(TURE){ think(); down(chopstick[LEFT[i]]); down(chopstick[RIGHT[i]]); eat(); up(chopstick[RIGHT[i]]); up(chopstick[LEFT[i]]); } }
為了防止死鎖的發生,可以加一點限制,只允許同時拿起左右兩邊的筷子,方法是引入一個互斥量,對拿起兩個筷子的那段程式碼加鎖。
semaphore mutex = 1; void philosopher(int i) { while(TURE){ think(); down(mutex); down(chopstick[LEFT[i]]); down(chopstick[RIGHT[i]]); up(mutex); eat(); down(mutex); up(chopstick[RIGHT[i]]); up(chopstick[LEFT[i]]); up(mutex); } }
第三章 死鎖
死鎖的條件
- 互斥
- 請求與保持:一個程序因請求資源而阻塞時,對已獲得的資源保持不放。
- 不可搶佔
- 環路等待
死鎖的處理方法
1. 鴕鳥策略
把頭埋在沙子裡,假裝根本沒發生問題。
這種策略不可取。
2. 死鎖預防
在程式執行之前預防發生死鎖。
2.1 破壞互斥條件
例如假離線印表機技術允許若干個程序同時輸出,唯一真正請求物理印表機的程序是印表機守護程序。
2.2 破壞請求與保持條件
一種實現方式是規定所有程序在開始執行前請求所需要的全部資源。
2.3 破壞不可搶佔條件
2.4 破壞環路等待
給資源統一編號,程序只能按編號順序來請求資源。
3. 死鎖避免
在程式執行時避免發生死鎖。
3.1 安全狀態
圖 a 的第二列 has 表示已擁有的資源數,第三列 max 表示總共需要的資源數,free 表示還有可以使用的資源數。從圖 a 開始出發,先讓 B 擁有所需的所有資源,執行結束後釋放 B,此時 free 變為 4;接著以同樣的方式執行 C 和 A,使得所有程序都能成功執行,因此可以稱圖 a 所示的狀態時安全的。
定義:如果沒有死鎖發生,並且即使所有程序突然請求對資源的最大需求,也仍然存在某種排程次序能夠使得每一個程序執行完畢,則稱該狀態是安全的。
3.2 單個資源的銀行家演算法
一個小城鎮的銀行家,他向一群客戶分別承諾了一定的貸款額度,演算法要做的是判斷對請求的滿足是否會進入不安全狀態,如果是,就拒絕請求;否則予以分配。
上圖 c 為不安全狀態,因此演算法會拒絕之前的請求,從而避免進入圖 c 中的狀態。
3.3 多個資源的銀行家演算法
上圖中有五個程序,四個資源。左邊的圖表示已經分配的資源,右邊的圖表示還需要分配的資源。最右邊的 E、P 以及 A 分別表示:總資源、已分配資源以及可用資源,注意這三個為向量,而不是具體數值,例如 A=(1020),表示 4 個資源分別還剩下 1/0/2/0。
檢查一個狀態是否安全的演算法如下:
① 查詢右邊的矩陣是否存在一行小於等於向量 A。如果不存在這樣的行,那麼系統將會發生死鎖,狀態是不安全的。
② 假若找到這樣一行,將該程序標記為終止,並將其已分配資源加到 A 中。
③ 重複以上兩步,直到所有程序都標記為終止,則狀態時安全的。
4. 死鎖檢測與死鎖恢復
不試圖組織死鎖,而是當檢測到死鎖發生時,採取措施進行恢復。
4.1 死鎖檢測演算法
死鎖檢測的基本思想是,如果一個程序所請求的資源能夠被滿足,那麼就讓它執行,釋放它擁有的所有資源,然後讓其它能滿足條件的程序執行。
上圖中,有三個程序四個資源,每個資料代表的含義如下:
E 向量:資源總量A 向量:資源剩餘量C 矩陣:每個程序所擁有的資源數量,每一行都代表一個程序擁有資源的數量R 矩陣:每個程序請求的資源數量
程序 P1 和 P2 所請求的資源都得不到滿足,只有程序 P3 可以,讓 P3 執行,之後釋放 P3 擁有的資源,此時 A = (2 2 2 0)。P1 可以執行,執行後釋放 P1 擁有的資源, A = (4 2 2 2) ,P2 也可以執行。所有程序都可以順利執行,沒有死鎖。
演算法總結如下:
每個程序最開始時都不被標記,執行過程有可能被標記。當演算法結束時,任何沒有被標記的程序都是死鎖程序。
① 尋找一個沒有標記的程序 Pi,它所請求的資源小於等於 A。② 如果找到了這樣一個程序,那麼將 C 矩陣的第 i 行向量加到 A 中,標記該程序,並轉回 ①。③ 如果有沒有這樣一個程序,演算法終止。
4.2 死鎖恢復
① 利用搶佔恢復② 殺死程序
第四章 儲存器管理
虛擬記憶體
每個程式擁有自己的地址空間,這個地址空間被分割成多個塊,每一塊稱為一 頁。這些頁被對映到實體記憶體,但不需要對映到連續的實體記憶體,也不需要所有頁都必須在實體記憶體中。
當程式引用到一部分在實體記憶體中的地址空間時,由硬體立即執行必要的對映。當程式引用到一部分不在實體記憶體中的地址空間時,由作業系統負責將缺失的部分裝入實體記憶體並重新執行失敗的指令。
分頁與分段
1. 分頁
使用者程式的地址空間被劃分為若干固定大小的區域,稱為“頁”。相應地,記憶體空間分成若干個物理塊,頁和塊的大小相等。可將使用者程式的任一頁放在記憶體的任一塊中,實現了離散分配,由一個頁表來維護它們之間的對映關係。
2. 分段
上圖為一個編譯器在編譯過程中建立的多個表,有 4 個表是動態增長的,如果使用分頁系統的一維地址空間,動態遞增的特點會導致覆蓋問題的出現。
分段的做法是把每個表分成段,一個段構成一個獨立的地址空間。每個段的長度可以不同,可以動態改變。
每個段都需要程式設計師來劃分。
3. 段頁式
用分段方法來分配和管理虛擬儲存器。程式的地址空間按邏輯單位分成基本獨立的段,而每一段有自己的段名,再把每段分成固定大小的若干頁。
用分頁方法來分配和管理實存。即把整個主存分成與上述頁大小相等的儲存塊,可裝入作業的任何一頁。程式對記憶體的調入或調出是按頁進行的。但它又可按段實現共享和保護。
4. 分頁與分段區別
① 對程式設計師的透明性:分頁透明,但是分段需要程式設計師顯示劃分每個段。
② 地址空間的維度:分頁是一維地址空間,分段是二維的。
③ 大小是否可以改變:頁的大小不可變,段的大小可以動態改變。
④ 出現的原因:分頁主要用於實現虛擬記憶體,從而獲得更大的地址空間;分段主要是為了使程式和資料可以被劃分為邏輯上獨立的地址空間並且有助於共享和保護。
頁面置換演算法
在程式執行過程中,若其所要訪問的頁面不在記憶體而需要把它們調入記憶體,但是記憶體已無空閒空間時,系統必須從記憶體中調出一個頁面到磁碟對換區中,並且將程式所需要的頁面調入記憶體中。頁面置換演算法的主要目標是使頁面置換頻率最低(也可以說缺頁率最低)。
1. 最佳(Optimal)
所選擇的被換出的頁面將是最長時間內不再被訪問,通常可以保證獲得最低的缺頁率。
是一種理論上的演算法,因為無法知道一個頁面多長時間會被再訪問到。
舉例:一個系統為某程序分配了三個物理塊,並有如下頁面引用序列:
7,0,1,2,0,3,0,4,2,3,0,3,2,1,2,0,1,7,0,1
程序執行時,先將 7,0,1 三個頁面裝入記憶體。當程序要訪問頁面 2 時,產生缺頁中斷,會將頁面 7 換出,因為頁面 7 再次被訪問的時間最長。
2. 先進先出(FIFO)
所選擇換出的頁面是最先進入的頁面。
該演算法會將那些經常被訪問的頁面也被換出,從而使缺頁率升高。
3. 最近最久未使用(LRU, Least Recently Used)
雖然無法知道將來要使用的頁面情況,但是可以知道過去使用頁面的情況。LRU 將最近最久未使用的頁面換出。
可以用棧來實現該演算法,棧中儲存頁面的頁面號。當程序訪問一個頁面時,將該頁面的頁面號從棧移除,並將它壓入棧頂,這樣,最近被訪問的頁面的頁面號總是在棧頂,而最近最久未使用的頁面的頁面號總是在棧底。
4,7,0,7,1,0,1,2,1,2,6
4. 時鐘(Clock)
Clock 頁面置換演算法需要用到一個訪問位,當一個頁面被訪問時,將訪問為置為 1。
首先,將記憶體中的所有頁面連結成一個迴圈佇列,當缺頁中斷髮生時,檢查當前指標所指向頁面的訪問位,如果訪問位為 0,就將該頁面換出;否則將該頁的訪問位設定為 0,給該頁面第二次的機會,移動指標繼續檢查。
第五章 裝置管理
磁碟排程演算法
當多個程序同時請求訪問磁碟時,需要進行磁碟排程來控制對磁碟的訪問。磁碟排程的主要目標是使磁碟的平均尋道時間最少。
1. 先來先服務(FCFS, First Come First Serverd)
根據程序請求訪問磁碟的先後次序來進行排程。優點是公平和簡單,缺點也很明顯,因為未對尋道做任何優化,使平均尋道時間可能較長。
2. 最短尋道時間優先(SSTF, Shortest Seek Time First)
要求訪問的磁軌與當前磁頭所在磁軌距離最近的優先進行排程。這種演算法並不能保證平均尋道時間最短,但是比 FCFS 好很多。
3. 掃描演算法(SCAN)
SSTF 會出現進行飢餓現象。考慮以下情況,新程序請求訪問的磁軌與磁頭所在磁軌的距離總是比一個在等待的程序來的近,那麼等待的程序會一直等待下去。
SCAN 演算法在 SSTF 演算法之上考慮了磁頭的移動方向,要求所請求訪問的磁軌在磁頭當前移動方向上才能夠得到排程。因為考慮了移動方向,那麼一個程序請求訪問的磁軌一定會得到排程。
當一個磁頭自裡向外移動時,移到最外側會改變移動方向為自外向裡,這種移動的規律類似於電梯的執行,因此又常稱 SCAN 演算法為電梯排程演算法。
4. 迴圈掃描演算法(CSCAN)
CSCAN 對 SCAN 進行了改動,要求磁頭始終沿著一個方向移動。
參考資料
Tanenbaum A S, Bos H. Modern operating systems[M]. Prentice Hall Press, 2014.
湯子瀛, 哲鳳屏, 湯小丹. 計算機作業系統[M]. 西安電子科技大學出版社, 2001.
Bryant, R. E., & O’Hallaron, D. R. (2004). 深入理解計算機系統.