460道Java後端面試高頻題答案版【模組六:電腦作業系統】

  • 2019 年 10 月 11 日
  • 筆記

寫在前面

1. 電腦作業系統和電腦網路是每個後端開發工程師必須掌握的知識。因為你寫的程式碼最終都是要在作業系統里跑的,弄懂作業系統的原理對你編寫高品質程式碼、調優、排故都有很大的幫助。在這裡說一下我作為非科班轉後端開發對電腦作業系統的看法,這一塊知識確實要比其他模組的知識要難理解,因為多了很多名詞和概念,更加抽象。但是呢,即便難度大,我們也必須征服它。因為很有可能你不跨越它,就見不到向你揮手的 offer 。無論是為了秋招還是為了以後當一名有「深度」的開發工程師,都是有必要去學習作業系統的。

2. 這裡給大家推薦兩本書,封面如下。我一直覺得對於電腦基礎的模組,看一本好書是最好的學習辦法。

2. 做筆記:電腦作業系統的知識點還是比較多的,需要看書的時候做好筆記,方便複習。而且做筆記的時候可以就這個知識點去百度下,看看有沒有自己遺漏的點,再給補充進來。這樣複習的時候,只用看筆記就可以了。

3. 看面經:經常刷一刷牛客,看看對於電腦作業系統,面試官們都是怎麼問的?很多問題你可能會,但是不懂面試官的問法,也會回答不上來;問到的題目自己是否準備了?而且對於電腦網路和電腦作業系統會因為公司和崗位的不同而有所側重的,多看看面經就會發現還是有一點規律的,但是這都不是絕對的,最後還要看面你的面試官的喜好。

電腦作業系統

1、簡單說下你對並發和並行的理解?

1. 並行是指兩個或者多個事件在同一時刻發生;而並發是指兩個或多個事件在同一時間間隔發生;

2. 並行是在不同實體上的多個事件,並發是在同一實體上的多個事件;

2、同步、非同步、阻塞、非阻塞的概念

同步:當一個同步調用發出後,調用者要一直等待返回結果。通知後,才能進行後續的執行。

非同步:當一個非同步過程調用發出後,調用者不能立刻得到返回結果。實際處理這個調用的部件在完成後,通過狀態、通知和回調來通知調用者。

阻塞:是指調用結果返回前,當前執行緒會被掛起,即阻塞。

非阻塞:是指即使調用結果沒返回,也不會阻塞當前執行緒。

3、進程和執行緒的基本概念

進程:進程是系統進行資源分配和調度的一個獨立單位,是系統中的並發執行的單位。

執行緒:執行緒是進程的一個實體,也是 CPU 調度和分派的基本單位,它是比進程更小的能獨立運行的基本單位,有時又被稱為輕權進程或輕量級進程。

4、進程與執行緒的區別?

1. 進程是資源分配的最小單位,而執行緒是 CPU 調度的最小單位;

2. 創建進程或撤銷進程,系統都要為之分配或回收資源,作業系統開銷遠大於創建或撤銷執行緒時的開銷;

3. 不同進程地址空間相互獨立,同一進程內的執行緒共享同一地址空間。一個進程的執行緒在另一個進程內是不可見的;

4. 進程間不會相互影響,而一個執行緒掛掉將可能導致整個進程掛掉;

5、為什麼有了進程,還要有執行緒呢?

進程可以使多個程式並發執行,以提高資源的利用率和系統的吞吐量,但是其帶來了一些缺點:

1. 進程在同一時間只能幹一件事情;

2. 進程在執行的過程中如果阻塞,整個進程就會被掛起,即使進程中有些工作不依賴與等待的資源,仍然不會執行。

基於以上的缺點,作業系統引入了比進程粒度更小的執行緒,作為並發執行的基本單位,從而減少程式在並發執行時所付出的時間和空間開銷,提高並發性能。

6、進程的狀態轉換

進程包括三種狀態:就緒態、運行態和阻塞態。

1. 就緒 —> 執行:對就緒狀態的進程,當進程調度程式按一種選定的策略從中選中一個就緒進程,為之分配了處理機後,該進程便由就緒狀態變為執行狀態;

2. 執行 —> 阻塞:正在執行的進程因發生某等待事件而無法執行,則進程由執行狀態變為阻塞狀態,如進程提出輸入/輸出請求而變成等待外部設備傳輸資訊的狀態,進程申請資源(主存空間或外部設備)得不到滿足時變成等待資源狀態,進程運行中出現了故障(程式出錯或主存儲器讀寫錯等)變成等待干預狀態等等;

3. 阻塞 —> 就緒:處於阻塞狀態的進程,在其等待的事件已經發生,如輸入/輸出完成,資源得到滿足或錯誤處理完畢時,處於等待狀態的進程並不馬上轉入執行狀態,而是先轉入就緒狀態,然後再由系統進程調度程式在適當的時候將該進程轉為執行狀態;

4. 執行 —> 就緒:正在執行的進程,因時間片用完而被暫停執行,或在採用搶先式優先順序調度演算法的系統中,當有更高優先順序的進程要運行而被迫讓出處理機時,該進程便由執行狀態轉變為就緒狀態。

7、進程間的通訊方式有哪些?

進程間通訊(IPC,InterProcess Communication)是指在不同進程之間傳播或交換資訊。IPC 的方式通常有管道(包括無名管道和命名管道)、消息隊列、訊號量、共享存儲、Socket、Streams 等。其中 Socket 和 Streams 支援不同主機上的兩個進程 IPC。

  • 管道

1. 它是半雙工的,具有固定的讀端和寫端;

2. 它只能用於父子進程或者兄弟進程之間的進程的通訊;

3. 它可以看成是一種特殊的文件,對於它的讀寫也可以使用普通的 read、write 等函數。但是它不是普通的文件,並不屬於其他任何文件系統,並且只存在於記憶體中。

  • 命名管道

1. FIFO 可以在無關的進程之間交換數據,與無名管道不同;

2. FIFO 有路徑名與之相關聯,它以一種特殊設備文件形式存在於文件系統中。

  • 消息隊列

1. 消息隊列,是消息的鏈接表,存放在內核中。一個消息隊列由一個標識符 ID 來標識;

2. 消息隊列是面向記錄的,其中的消息具有特定的格式以及特定的優先順序;

3. 消息隊列獨立於發送與接收進程。進程終止時,消息隊列及其內容並不會被刪除;

4. 消息隊列可以實現消息的隨機查詢,消息不一定要以先進先出的次序讀取,也可以按消息的類型讀取。

  • 訊號量

1. 訊號量(semaphore)是一個計數器。用於實現進程間的互斥與同步,而不是用於存儲進程間通訊數據;

2. 訊號量用於進程間同步,若要在進程間傳遞數據需要結合共享記憶體;

3. 訊號量基於作業系統的 PV 操作,程式對訊號量的操作都是原子操作;

4. 每次對訊號量的 PV 操作不僅限於對訊號量值加 1 或減 1,而且可以加減任意正整數;

5. 支援訊號量組。

  • 共享記憶體

1. 共享記憶體(Shared Memory),指兩個或多個進程共享一個給定的存儲區;

2. 共享記憶體是最快的一種 IPC,因為進程是直接對記憶體進行存取。

8、進程的調度演算法有哪些?

調度演算法是指:根據系統的資源分配策略所規定的資源分配演算法。常用的調度演算法有:先來先服務調度演算法、時間片輪轉調度法、短作業優先調度演算法、最短剩餘時間優先、高響應比優先調度演算法、優先順序調度演算法等等。

  • 先來先服務調度演算法

先來先服務調度演算法是一種最簡單的調度演算法,也稱為先進先出或嚴格排隊方案。當每個進程就緒後,它加入就緒隊列。當前正運行的進程停止執行,選擇在就緒隊列中存在時間最長的進程運行。該演算法既可以用於作業調度,也可以用於進程調度。先來先去服務比較適合於常作業(進程),而不利於段作業(進程)。

  • 時間片輪轉調度演算法

時間片輪轉調度演算法主要適用於分時系統。在這種演算法中,系統將所有就緒進程按到達時間的先後次序排成一個隊列,進程調度程式總是選擇就緒隊列中第一個進程執行,即先來先服務的原則,但僅能運行一個時間片。

  • 短作業優先調度演算法

短作業優先調度演算法是指對短作業優先調度的演算法,從後備隊列中選擇一個或若干個估計運行時間最短的作業,將它們調入記憶體運行。 短作業優先調度演算法是一個非搶佔策略,他的原則是下一次選擇預計處理時間最短的進程,因此短進程將會越過長作業,跳至隊列頭。

  • 最短剩餘時間優先調度演算法

最短剩餘時間是針對最短進程優先增加了搶佔機制的版本。在這種情況下,進程調度總是選擇預期剩餘時間最短的進程。當一個進程加入到就緒隊列時,他可能比當前運行的進程具有更短的剩餘時間,因此只要新進程就緒,調度程式就能可能搶佔當前正在運行的進程。像最短進程優先一樣,調度程式正在執行選擇函數是必須有關於處理時間的估計,並且存在長進程飢餓的危險。

  • 高響應比優先調度演算法

高響應比優先調度演算法主要用於作業調度,該演算法是對 先來先服務調度演算法和短作業優先調度演算法的一種綜合平衡,同時考慮每個作業的等待時間和估計的運行時間。在每次進行作業調度時,先計算後備作業隊列中每個作業的響應比,從中選出響應比最高的作業投入運行。

  • 優先順序調度演算法

優先順序調度演算法每次從後備作業隊列中選擇優先順序最髙的一個或幾個作業,將它們調入記憶體,分配必要的資源,創建進程並放入就緒隊列。在進程調度中,優先順序調度演算法每次從就緒隊列中選擇優先順序最高的進程,將處理機分配給它,使之投入運行。

9、什麼是死鎖?

死鎖,是指多個進程在運行過程中因爭奪資源而造成的一種僵局,當進程處於這種僵持狀態時,若無外力作用,它們都將無法再向前推進。 如下圖所示:如果此時有一個執行緒 A,已經持有了鎖 A,但是試圖獲取鎖 B,執行緒 B 持有鎖 B,而試圖獲取鎖 A,這種情況下就會產生死鎖。

10、產生死鎖的原因?

由於系統中存在一些不可剝奪資源,而當兩個或兩個以上進程佔有自身資源,並請求對方資源時,會導致每個進程都無法向前推進,這就是死鎖。

  • 競爭資源

例如:系統中只有一台印表機,可供進程 A 使用,假定 A 已佔用了印表機,若 B 繼續要求印表機列印將被阻塞。

系統中的資源可以分為兩類:

1. 可剝奪資源:是指某進程在獲得這類資源後,該資源可以再被其他進程或系統剝奪,CPU 和主存均屬於可剝奪性資源;

2. 不可剝奪資源,當系統把這類資源分配給某進程後,再不能強行收回,只能在進程用完後自行釋放,如磁帶機、印表機等。

  • 2. 進程推進順序不當

例如:進程 A 和 進程 B 互相等待對方的數據。

11、死鎖產生的必要條件?

1. 互斥條件:進程要求對所分配的資源進行排它性控制,即在一段時間內某資源僅為一進程所佔用。

2. 請求和保持條件:當進程因請求資源而阻塞時,對已獲得的資源保持不放。

3. 不剝奪條件:進程已獲得的資源在未使用完之前,不能剝奪,只能在使用完時由自己釋放。

4. 環路等待條件:在發生死鎖時,必然存在一個進程–資源的環形鏈。

12、解決死鎖的基本方法?

1. 預防死鎖

2. 避免死鎖

3. 檢測死鎖

4. 解除死鎖

13、怎麼預防死鎖?

1. 破壞請求條件:一次性分配所有資源,這樣就不會再有請求了;

2. 破壞請保持條件:只要有一個資源得不到分配,也不給這個進程分配其他的資源:

3. 破壞不可剝奪條件:當某進程獲得了部分資源,但得不到其它資源,則釋放已佔有的資源;

4. 破壞環路等待條件:系統給每類資源賦予一個編號,每一個進程按編號遞增的順序請求資源,釋放則相反。

14、怎麼避免死鎖?

  • 銀行家演算法

當進程首次申請資源時,要測試該進程對資源的最大需求量,如果系統現存的資源可以滿足它的最大需求量則按當前的申請量分配資源,否則就推遲分配。

當進程在執行中繼續申請資源時,先測試該進程已佔用的資源數與本次申請資源數之和是否超過了該進程對資源的最大需求量。若超過則拒絕分配資源。若沒超過則再測試系統現存的資源能否滿足該進程尚需的最大資源量,若滿足則按當前的申請量分配資源,否則也要推遲分配。

  • 安全序列

是指系統能按某種進程推進順序(P1, P2, P3, …, Pn),為每個進程 Pi 分配其所需要的資源,直至滿足每個進程對資源的最大需求,使每個進程都可以順序地完成。這種推進順序就叫安全序列【銀行家演算法的核心就是找到一個安全序列】。

  • 系統安全狀態

如果系統能找到一個安全序列,就稱系統處於安全狀態,否則,就稱系統處於不安全狀態。

15、怎麼解除死鎖?

1. 資源剝奪:掛起某些死鎖進程,並搶佔它的資源,將這些資源分配給其他死鎖進程(但應該防止被掛起的進程長時間得不到資源);

2. 撤銷進程:強制撤銷部分、甚至全部死鎖進程並剝奪這些進程的資源(撤銷的原則可以按進程優先順序和撤銷進程代價的高低進行);

3. 進程回退:讓一個或多個進程回退到足以避免死鎖的地步。進程回退時自願釋放資源而不是被剝奪。要求系統保持進程的歷史資訊,設置還原點。

16、什麼是緩衝區溢出?有什麼危害?

緩衝區為暫時置放輸出或輸入資料的記憶體。緩衝區溢出是指當電腦向緩衝區填充數據時超出了緩衝區本身的容量,溢出的數據覆蓋在合法數據上。造成緩衝區溢出的主要原因是程式中沒有仔細檢查用戶輸入是否合理。電腦中,緩衝區溢出會造成的危害主要有以下兩點:程式崩潰導致拒絕服務和跳轉並且執行一段惡意程式碼。

17、分頁與分段的區別?

1. 段是資訊的邏輯單位,它是根據用戶的需要劃分的,因此段對用戶是可見的 ;頁是資訊的物理單位,是為了管理主存的方便而劃分的,對用戶是透明的;

2. 段的大小不固定,有它所完成的功能決定;頁大大小固定,由系統決定;

3. 段向用戶提供二維地址空間;頁向用戶提供的是一維地址空間;

4. 段是資訊的邏輯單位,便於存儲保護和資訊的共享,頁的保護和共享受到限制。

18、物理地址、邏輯地址、虛擬記憶體的概念

1. 物理地址:它是地址轉換的最終地址,進程在運行時執行指令和訪問數據最後都要通過物理地址從主存中存取,是記憶體單元真正的地址。

2. 邏輯地址:是指電腦用戶看到的地址。例如:當創建一個長度為 100 的整型數組時,作業系統返回一個邏輯上的連續空間:指針指向數組第一個元素的記憶體地址。由於整型元素的大小為 4 個位元組,故第二個元素的地址時起始地址加 4,以此類推。事實上,邏輯地址並不一定是元素存儲的真實地址,即數組元素的物理地址(在記憶體條中所處的位置),並非是連續的,只是作業系統通過地址映射,將邏輯地址映射成連續的,這樣更符合人們的直觀思維。

3. 虛擬記憶體:是電腦系統記憶體管理的一種技術。它使得應用程式認為它擁有連續的可用的記憶體(一個連續完整的地址空間),而實際上,它通常是被分隔成多個物理記憶體碎片,還有部分暫時存儲在外部磁碟存儲器上,在需要時進行數據交換。

19、頁面置換演算法有哪些?

請求調頁,也稱按需調頁,即對不在記憶體中的「頁」,當進程執行時要用時才調入,否則有可能到程式結束時也不會調入。而記憶體中給頁面留的位置是有限的,在記憶體中以幀為單位放置頁面。為了防止請求調頁的過程出現過多的記憶體頁面錯誤(即需要的頁面當前不在記憶體中,需要從硬碟中讀數據,也即需要做頁面的替換)而使得程式執行效率下降,我們需要設計一些頁面置換演算法,頁面按照這些演算法進行相互替換時,可以盡量達到較低的錯誤率。常用的頁面置換演算法如下:

  • 先進先出置換演算法(FIFO)

先進先出,即淘汰最早調入的頁面。

  • 最佳置換演算法(OPT)

選未來最遠將使用的頁淘汰,是一種最優的方案,可以證明缺頁數最小。

  • 最近最久未使用(LRU)演算法

即選擇最近最久未使用的頁面予以淘汰

  • 時鐘(Clock)置換演算法

時鐘置換演算法也叫最近未用演算法 NRU(Not RecentlyUsed)。該演算法為每個頁面設置一位訪問位,將記憶體中的所有頁面都通過鏈接指針鏈成一個循環隊列。

20、談談你對動態鏈接庫和靜態鏈接庫的理解?

靜態鏈接就是在編譯鏈接時直接將需要的執行程式碼拷貝到調用處,優點就是在程式發布的時候就不需要的依賴庫,也就是不再需要帶著庫一塊發布,程式可以獨立執行,但是體積可能會相對大一些。

動態鏈接就是在編譯的時候不直接拷貝可執行程式碼,而是通過記錄一系列符號和參數,在程式運行或載入時將這些資訊傳遞給作業系統,作業系統負責將需要的動態庫載入到記憶體中,然後程式在運行到指定的程式碼時,去共享執行記憶體中已經載入的動態庫可執行程式碼,最終達到運行時連接的目的。優點是多個程式可以共享同一段程式碼,而不需要在磁碟上存儲多個拷貝,缺點是由於是運行時載入,可能會影響程式的前期執行性能。