作業系統面試知識點總結
作業系統面試知識點總結
一.作業系統概述
1.作業系統主要功能
- 對計算機硬體資源進行管理,排程,分配
- 向用戶提供一個與系統互動的友好頁面
2.作業系統的四個特徵
作業系統擁有 4 個鮮明的特徵:併發、共享、虛擬和非同步。其中,併發和共享是作業系統的最基本特徵,沒有併發和共享,就談不上虛擬和非同步
-
併發和並行:
- 併發:併發是指巨集觀上在一段時間內能同時執行多個程式。當然,這些程式巨集觀上是同時發生的,但微觀上是交替發生的(同一時刻只有一個程式在執行)。作業系統通過引入程序和執行緒,使得程式能夠併發執行。
- 並行:並行則指同一時刻能執行多個指令,指兩個或多個事件在同一時刻同時發生。並行需要硬體支援
說到併發與並行,不得不提 CPU,作為計算機的大腦, CPU 主要和記憶體進行互動,從記憶體中提取指令並執行。而一個程式需要放入記憶體並給它分配 CPU 才能執行,所以併發並行的能力與 CPU 的效能息息相關:
- 單核 CPU同一時刻只能執行一個程式,各個程式只能併發地執行 ;
- 多核 CPU同一時刻可以同時執行多個程式,多個程式可以並行地執行。
比如 Intel 的第八代 i3 處理器就是 4 核 CPU,意味著可以並行地執行 4 個程式。當然,即使是對於 4 核 CPU 來說,只要有 4 個以上的程式需要 “同時” 執行,那麼併發性依然是必不可少的,因此併發性是作業系統一個最基本的特徵
-
共享:
共享即資源共享,是指系統中的資源可供記憶體中多個併發執行的程序共同使用。
共享分為兩類:互斥共享和同時共享
互斥共享:雖然這個資源是共享的,所有程序都能夠使用,但是同一個資源在某一時刻只允許一個程序訪問,也稱為互斥訪問,需要用同步機制來實現互斥訪問。互斥共享/訪問的資源稱為臨界資源。
比如:如果我們同時使用 QQ 和微信視訊,同一時間段內攝像頭資源只能分配給其中的一個程序。
同時共享:同時共享與互斥共享相反,允許一個時間段內多個程序 “同時” 對系統中的某些資源進行訪問。當然,所謂的 “同時” 往往是巨集觀上的,而在微觀上,這些程序可能是交替地對該資源進行訪問(即分時共享)。
比如:使用 QQ 傳送硬碟上的檔案 A,同時使用微信傳送硬碟上的檔案 B。巨集觀上看,兩邊在同時讀取併發送檔案, 都在訪問硬碟資源,並從中讀取資料。微觀上看,QQ 和微信這兩個程序是交替訪問硬碟資源的。
-
虛擬:
虛擬是指把一個物理上的實體變為若干個邏輯上的對應物。物理實體(前者)是實際存在的,而邏輯上對應物(後者)是使用者感受到的。
兩種虛擬技術:空分複用,時分複用
空分複用:比如虛擬記憶體:就是把記憶體作為快取記憶體來使用,只用來儲存最頻繁使用的部分程式,而把程式的大部分放在磁碟上。這種機制需要快速的映像記憶體地址,以便把程式生成的地址轉換為有關位元組在記憶體中的實體地址。這種映像由 CPU 中的一個部件,稱為儲存器管理單元(Memory Management Unit,MMU)來完成。
虛擬磁碟:物理磁碟虛擬為多個邏輯磁碟,如C、D、E等邏輯盤,使用起來更加安全、方便
時分複用:多個程序能在同一個 CPU 上併發執行就是因為使用了時分複用技術,讓每個程序輪流佔用處理器,每次只執行一小個時間片並快速切換。 顯然,如果失去了併發性,一個時間段內系統中只能執行一道程式,那也就失去了實現虛擬性的意義了。因此,沒有併發性,就談不上虛擬性
-
非同步和同步[1]:
同步:所謂同步,就是在發出一個呼叫時,在沒有得到結果之前,該呼叫就不返回。但是一旦呼叫返回,就得到返回值了。
換句話說,就是由呼叫者主動等待這個呼叫的結果。非同步:而非同步則是相反,呼叫在發出之後,這個呼叫就直接返回了,所以沒有返回結果。換句話說,當一個非同步過程呼叫發出後,呼叫者不會立刻得到結果。而是在呼叫發出後,被呼叫者通過狀態、通知來通知呼叫者*,或通過回撥函式處理這個呼叫。
你打電話問書店老闆有沒有《分散式系統》這本書,如果是同步通訊機制,書店老闆會說,你稍等,”我查一下",然後開始查啊查,等查好了(可能是5秒,也可能是一天)告訴你結果(返回結果)。
而非同步通訊機制,書店老闆直接告訴你我查一下啊,查好了打電話給你,然後直接掛電話了(不返回結果)。然後查好了,他會主動打電話給你。在這裡老闆通過“回電”這種方式來回調。
3.阻塞與非阻塞
- 阻塞是指呼叫結果返回之前,當前執行緒會被掛起。呼叫執行緒只有在得到結果之後才會返回。
- 非阻塞呼叫指在不能立刻得到結果之前,該呼叫不會阻塞當前執行緒
你打電話問書店老闆有沒有《分散式系統》這本書,你如果是阻塞式呼叫,你會一直把自己“掛起”,直到得到這本書有沒有的結果,如果是非阻塞式呼叫,你不管老闆有沒有告訴你,你自己先一邊去玩了, 當然你也要偶爾過幾分鐘check一下老闆有沒有返回結果。[1]
4.程序和執行緒
1)程序:是作業系統為各種程式分配資源的最小單位,(程式是一些儲存在磁碟上的指令的有序集合),是程式的一次執行過程,不僅包含正在執行的程式實體,並且包括這個執行的程式中佔據的所有系統資源,比如說 CPU、記憶體、網路資源等。
2)執行緒:是作業系統排程的最小單元,一個程序中可以有多個執行緒,它們共享程序資源
一個程式至少有一個程序,一個程序至少有一個執行緒
舉個例子,QQ 和 Chrome 瀏覽器是兩個程序,Chrome 程序裡面有很多執行緒,例如 HTTP 請求執行緒、事件響應執行緒、渲染執行緒等等,執行緒的併發執行使得在瀏覽器中點選一個新連結從而發起 HTTP 請求時,瀏覽器還可以響應使用者的其它事件。[2]
5.核心態和使用者態
什麼是核心:
現代作業系統都採用程序的概念,為了更好的處理系統的併發性、共享性等,並使程序能夠協調地工作,僅依靠計算機硬體提供的功能是遠遠不夠的。例如,程序的排程就不能用硬體來實現,必須使用一組基本軟體對硬體資源進行改造,以便為程序的執行提供良好的執行環境,這個軟體就是核心(kernel)。簡單的來說核心就是作業系統中的一組程式模組,作為可信軟體來提供支援程序併發執行的基本功能和基本操作,具有訪問硬體裝置和所有記憶體空間的許可權。
當然,作業系統除了核心程式外,還有包括其他一些基本元件,如文字編輯器、編譯器、用來與使用者進行互動的程式比如桌面系統等。
什麼是核心態和使用者態:
那麼既然核心是程式,它需要執行,就必須被分配 CPU。因此,CPU 上會執行兩種程式,一種是作業系統的核心程式(也稱為系統程式),一種是應用程式。前者完成系統任務,後者實現應用任務。兩者之間有控制和被控制的關係,前者有權管理和分配資源,而後者只能向系統申請使用資源。
顯然,我們應該把在 CPU 上執行的這兩類程式加以區分,這就是核心態和使用者態出現的原因
使用者態和核心態其實就是CPU執行使用者程式還是作業系統核心程式的表現
核心態:cpu執行作業系統核心程式時,CPU所處的狀態是核心態,此時執行在核心態的程式可以訪問計算機的任何資源,不受限制,為所欲為,例如協調 CPU 資源,分配記憶體資源,提供穩定的環境供應用程式執行等。
使用者態:CPU執行使用者程式所處的狀態,執行在使用者態的程式只能訪問當前 CPU 上執行程式所在的記憶體地址空間,這樣有效地防止了作業系統程式受到應用程式的侵害
6.核心態和使用者態的轉換
在合適的情況下,作業系統的核心會把 CPU 的使用權主動讓給應用程式,也就是使 CPU 從核心態轉換到使用者態。而 CPU 要想從使用者態回到核心態,只能通過中斷機制完成,如果沒有中斷機制,那麼一旦應用程式上 CPU 執行(使用者態),CPU 就會一直執行這個應用程式。也就是說,中斷是讓作業系統核心奪回 CPU 使用權的唯一途徑。可以說,作業系統是由中斷驅動的。
這裡的中斷機制具體指三種:系統呼叫,中斷,異常
異常(也稱內中斷):當CPU在執行執行在使用者態下的程式時,發生了某些事先不可知的異常,這時會觸發由當前執行程序切換到處理此異常的核心相關程式中,也就轉到了核心態。比如缺頁異常,如非法操作碼、地址越界、算術溢位,除數為 0 等。
中斷(狹義上的中斷,也稱外中斷):外中斷與當前執行的指令無關, 中斷訊號來源於 CPU 外部。如 I/O 完成中斷,當外圍裝置完成使用者請求的操作後,會向CPU發出相應的中斷訊號,這時CPU會暫停執行下一條即將要執行的指令轉而去執行與中斷訊號對應的處理程式。此外還有時鐘中斷、控制檯中斷等。
系統呼叫:使用者態主動切換到核心態的一種方式,使用者態程序通過系統呼叫申請使用作業系統提供的服務程式完成工作,比如 read 操作,fork() 操作(就是執行了一個建立新程序的系統呼叫)。說的更詳細點,作業系統作為計算機硬體之上的第一層軟體,需要向上層提供一些簡單易用的服務,這個上層包括使用者和應用程式:
給使用者提供的介面有圖形介面 GUI 和命令介面,給應用程式提供的是程式介面,這個程式介面就是由一組系統呼叫組成的,是作業系統提供給開發人員使用的。可以理解為一種可供應用程式呼叫的特殊函式,應用程式可以通過系統呼叫來請求獲得作業系統核心的服務。
系統呼叫的過程簡略版大致如下:
1)在使用者態,應用程式傳遞系統呼叫引數
2)執行陷入指令(read,fork等等),引發一個內中斷,使 CPU 進入核心態
3)在核心態,執行相應的請求,核心程式處理系統呼叫
4)返回應用程式
二.系統呼叫
1.什麼情況下會用到系統呼叫
舉個例子:我們去學校列印店列印論文,你按下了 WPS 的 “列印” 選項,於是印表機開始工作。 你的論文列印到一半時,另一位同學按下了 Word 的 “列印” 按鈕,開始列印他自己的論文。想象一下如果兩個程序可以隨意的、併發的共享印表機資源,會發生什麼情況?
顯然,兩個程序併發執行,導致印表機裝置交替的收到 WPS 和 Word 兩個程序發來的列印請求,結果兩篇論文的內容混雜在一起了
如何解決這個問題?這就需要作業系統核心對共享資源進行統一的管理,並向上層提供 “系統呼叫” ,執行在使用者態的應用程式或者程序想要使用印表機這種共享資源,只能通過系統呼叫向作業系統核心發出請求,然後核心會對各個請求進行協調處理(程序排程)。
通過上面這個例子,我們就可以總結出什麼功能會用到系統呼叫:凡是與共享資源有關的操作(比如記憶體分配、I/O 操作、檔案管理等),都必須通過系統呼叫的方式向作業系統核心提出請求,由作業系統核心代為完成。這樣可以保證系統的穩定性和安全性,防止使用者進行非法操作。
2.系統呼叫大致分為5類
這些系統呼叫按功能大致可分為如下幾類:
-
裝置管理。完成裝置的請求或釋放,以及裝置啟動等功能。
作業系統必須高效的管理 I/O 裝置,它需要向 I/O 裝置傳送命令,捕捉中斷,並處理裝置的各種錯誤,它還應該在裝置和系統的其他部分之間提供簡單且易用的介面。
-
檔案管理。完成檔案的讀、寫、建立及刪除等功能。
檔案其實是程序建立的資訊邏輯單元,一個磁碟可能含有幾千甚至幾百萬個檔案,每個檔案都是獨立於其他檔案的,事實上,把每個檔案看成一種地址空間更容易理解檔案的本質。
檔案同樣是受作業系統管理的,有關檔案的構造、命名、存取、使用、保護、實現和管理方法都是作業系統設計的內容,這就是檔案系統的主題。
-
程序管理
1)程序排程。完成程序的建立、撤銷、阻塞及喚醒等功能。 通常情況下,會有多個程序或執行緒同時競爭 CPU,如果恰好只有一個 CPU 可用,這就導致 CPU 必須對下一個執行的程序或執行緒做出選擇,這個選擇的過程就是程序排程。
2)程序通訊。完成程序之間的訊息傳遞或訊號傳遞等功能。
程序通訊顧名思義,就是程序之間的相互交流。CPU 作為計算機最寶貴的資源,一個程序需要放入記憶體並給它分配 CPU 才能執行,而一個程式可能包含多個程序,這就需要程序之間進行相互交流,彼此同步,共同完成這個程式。舉個例子,如果程序 A 產生資料而程序 B 列印資料,那麼 B 在 A 產生資料之前就必須等待,那麼 A 是不是就得給 B 發訊息,告訴 B 我生產了資料,你可以列印了。
-
記憶體管理。完成記憶體的分配、回收以及獲取作業佔用記憶體區大小及地址等功能。
三.程序管理詳解
1.程序和執行緒的建立和撤銷過程
程序/執行緒的建立:
- 申請PCB
- 初始化程序描述資訊
- 為程序分配資源及地址空間
- 將其插入就緒佇列中
程序允許建立和控制另一個程序,前者稱為父程序,後者稱為子程序,子程序又可建立孫程序,子程序可以從父程序那裡繼承所有的資源,子程序撤銷時便可將獲得的資源歸還。撤銷父程序,必須撤銷所有的子程序。
程序的撤銷:
-
查詢需要撤銷的程序的PCB
-
如果程序處於執行狀態,則終止程序並進行排程
-
終止其子孫程序,並歸還資源
-
將它從所在佇列中刪除
2.程序的五種狀態
建立狀態、就緒狀態、執行狀態、阻塞狀態、結束狀態
- 只有就緒態和執行態能夠相互轉換,程序為就緒態時,等待cpu分配時間片,得到時間片後進入執行態
- 執行態的程序使用完時間片後,又重新回到就緒態
- 執行態的程序需要等待某個資源時(比如印表機資源),而進入阻塞態,阻塞態得到對應的資源時,又會回到就緒態
3.程序排程演算法
按照系統的不同分為兩大類:
3.1.批處理系統
-
先來先服務
非搶佔式排程演算法,按照程序請求順序進行排程
-
短作業優先
按程序的估計執行時間,最短的優先執行
-
最短剩餘時間優先
短作業優先的搶佔式版本,按剩餘時間的順序進行排程。當一個新作業到達時,其整個隱形時間和當前程序的剩餘時間相比,如果新的程序需要的時間更少,則掛起當前程序,執行新的程序。否則新程序等待。
3.2.互動式系統
-
時間片輪轉(時間片太小,導致程序切換頻繁,浪費時間)
將所有就緒程序按 FCFS 的原則排成一個佇列,每次排程時,把 CPU 時間分配給隊首程序,該程序可以執行一個時間片。當時間片用完時,由計時器發出時鐘中斷,排程程式便停止該程序的執行,並將它送往就緒佇列的末尾,同時繼續把 CPU 時間分配給隊首的程序。
-
優先順序排程
為每個程序分配一個優先順序,按優先順序進行排程。為了防止低優先順序的程序永遠等不到排程,可以隨著時間的推移增加等待程序的優先順序。
-
多級反饋佇列
時間片輪轉排程演算法和優先順序排程演算法的結合
為程序設定多個佇列,每個佇列中程序的優先順序和時間片都不同
4. 程序通訊的方式
-
建立管道進行通訊。
可以用 mkfifo 命令建立一個命名管道,可以用一個程序向管道里寫資料,然後可以讓另一個程序把裡面的資料讀出來。
-
訊息佇列
訊息佇列的通訊模式是這樣的:a 程序要給 b 程序發訊息,只需要把訊息掛在訊息佇列(可以是中介郵局,也可以是程序自己的信箱)裡就行了,b 程序需要的時候再去取訊息佇列裡的訊息
-
共享記憶體
共享記憶體是最快的一種程序通訊的方式,因為程序是直接對記憶體進行存取的。因為可以多個程序對共享記憶體同時操作,所以對共享空間的訪問必須要求程序對共享記憶體的訪問是互斥的。所以我們經常把訊號量和共享記憶體一起使用來實現程序通訊。(系統載入一個程序的時候,分配給程序的記憶體並不是實際的實體記憶體,而是虛擬記憶體空間。那麼我們可以讓兩個程序各自拿出一塊兒虛擬地址空間來,對映到同一個實體記憶體中。這樣兩個程序雖然有獨立的虛擬記憶體空間,但有一部分是對映到相同的實體記憶體,這樣就完成共享機制了)
5.死鎖
5.1.發生死鎖需要滿足以下條件:
-
互斥條件
資源的分配是互斥的,資源要麼處於被分配給一個程序的狀態(此時其他程序不可用),要麼就是可被其他程序可用狀態
-
等待和佔有條件
程序在請求資源得不到滿足時,進入阻塞狀態,且不是放已經佔有的資源
-
不剝奪條件
已經分配給一個程序的資源不能強制性地被搶佔,只能等待佔有他的程序釋放
-
環路等待
有兩個或者兩個以上的程序組成一條環路,該環路中的每個程序都在等待下一個程序釋放所佔有的資源
5.2.避免發生死鎖
-
預防策略
破壞死鎖發生的四個條件中的一個或者多個
-
銀行家演算法
5.3.如果已經發生死鎖如何消除
- 撤銷程序:
- 撤消陷於死鎖的全部程序;
- 逐個撤消陷於死鎖的程序,直到死鎖不存在;
- 資源剝奪,
- 從陷入死鎖的程序中逐個強迫放棄所佔用的資源,直至死鎖消失;
- 從另外的程序那裡強行剝奪足夠數量的資源分配給死鎖程序,以解除死鎖狀態
四.記憶體管理詳解
1.記憶體管理的幾種方式
-
分塊管理
是連續管理的一種,把記憶體分為幾個大小相等且固定的塊,每個程序佔用其中一個,如果程序很小的話,會浪費大量的空間。已經淘汰。
-
分頁管理
把記憶體分為若干個很小的頁面,相對比分塊的劃分力度更大一些。提高記憶體利用率。減少碎片,頁式管理通過頁表對應邏輯地址和實體地址。
-
分段管理
把記憶體分為幾個大小不定的有實際意義的段,比如 main 函式段,區域性變數段,程式碼段,通過管理段表來把邏輯地址轉為實體地址。
-
段頁式管理
結合了段式管理和頁面管理的優點,把主存先分為若干個段,每個段又分為若干個頁,也就是說段頁式管理的段與段以及段的內部都是離散的。
2.快表和多級頁表
2.1.塊表
塊表又稱為聯想暫存器(TLB),是一種訪問速度比記憶體快很多的高速緩衝儲存器,用來存放當前訪問的若干頁表項(沒有快表的話則需要到記憶體中訪問頁表,記憶體中的頁表叫做慢表),來加速有邏輯地址到實體地址轉換的速度。
2.2.塊表中存放的是那些頁表呢
根據區域性性原理,被訪問後的記憶體塊兒很可能在短時間內再次被訪問(因為程式中存在很多迴圈語句),可能程式在一段時間內會多次訪問同一個頁表項。所以在每次訪問頁表項時,先在快表裡查詢是否有該頁表項,如果沒有再去頁表中查詢,並把查到的頁表項放入快表。如果快表滿了,就根據一些策略把裡面的頁表項淘汰掉,再把新查詢的頁表加入進去。
2.3.多級頁表
多級頁表是為了解決頁表在記憶體中佔用空間太大的問題
在引入多級頁表之前,我們使用單級頁表來進行儲存頁表項,假如虛擬記憶體為 4GB,每個頁大小為 4KB,那麼需要的頁表項就為 4GB / 4KB = 1M 個!每個頁表項一般為 4B,那麼就需要 4MB 的空間,大概需要佔用 1000 個頁來存頁表項,存頁表項花費了很多記憶體空間。
所以如果引入兩級頁表,讓一級頁表的每個頁表項不再對映 4KB,而是對映 4MB,那麼需要的一級頁表項的個數為 4GB / 4MB = 1K 個,再讓每個一級的頁表項對映 一個二級頁表(二級頁表中包含1K 個(1024個)二級頁表項)。
下面是一個二級頁表邏輯地址轉實體地址的例子
3.虛擬地址和實體地址
我們寫程式的時候,打交道的是虛擬地址。這個虛擬地址由作業系統決定,而實體地址指的是真實記憶體地址暫存器的地址。現代處理器通常使用虛擬定址,用 MMU 把虛擬地址翻譯成實體地址才能訪問到真正的實體地址。
3.1.為什麼要有虛擬地址
- 沒有虛擬地址,我們直接訪問實體地址,這樣使用者程式可以直接訪問底層實體地址,很容易破壞作業系統。造成系統崩潰
- 想要同時執行多個程式特別困難,多個程式可能對同一個暫存器進行操作,會發生崩潰
4.虛擬記憶體
- 傳統的記憶體管理必須把作業一次性的 load 到記憶體中,並且一直駐留到其作業執行結束,當作業很大時,是沒有辦法一次性裝入記憶體的
- 而在一段時間內,只需要訪問小部分資料就可以保證程式的正常執行。所以基於區域性性原理,在程式載入的時候,把很快就會用到的部分放入記憶體中,暫時用不到的部分留在磁碟上。
其實虛擬記憶體的基礎是區域性性原理,也正是因為有區域性性原理,程式執行時才可以做到只裝入部分到記憶體就可以執行
5.虛擬記憶體的幾種實現
5.1.請求分頁式儲存管理
建立在分頁管理的基礎之上,為了支援虛擬記憶體實現了請求調頁和頁面置換功能。
- 首先作業執行時,僅裝入當前要執行的部分頁面即可
- 在執行的過程中,發現要請求的頁面不在記憶體中,那麼處理器通知作業系統按照對應的頁面置換演算法把相應的頁面調入到記憶體中。
- 如果發現在把頁面調入記憶體時,記憶體已滿,同時也可以把不用的頁面置換出去,以便騰出空間裝入新的頁面。
5.2.請求分段式儲存管理
只是把分頁管理換成了分段管理
5.3.請求段頁式儲存管理
同上
5.4.虛擬記憶體的請求分頁儲存管理和記憶體管理機制的不同
虛擬記憶體的請求分頁式儲存管理建立在分頁管理之上,他們的根本區別是用不用把程式所需的全部地址空間 load 到記憶體裡。請求分頁式不需要全部 load 到記憶體中,而分頁式管理需要,前者能夠提供虛擬記憶體,後者不可以!
6.頁面置換演算法
當使用請求分頁儲存管理記憶體時,如果發生缺頁中斷(就是要訪問的頁面不在記憶體中,這時就需要作業系統把其調入主存後再進行訪問)。且記憶體中沒有空閒,此時就必須在記憶體中根據一定的方法來清空一些目前用不到的頁面(記憶體),這樣騰出空間來裝新的內容。
6.1.先到先出演算法(FIFO)
把在記憶體中停留時間最長的頁面置換出去
6.2.最佳頁面置換(OPT)
把後面永遠用不到的或者最長時間用不到的記憶體頁置換出去
6.3.最近最久未使用頁面置換演算法(LRU)
LRU演算法給每個頁面一個訪問欄位。來記錄一個頁面最近一次訪問到現在經歷的時間T,需要置換出一個頁面時,把T最大的那個頁面置換出去即可
6.4.最少使用演算法LFU
把使用最少的頁面淘汰掉