文章目錄
- 前言
- 一、阻塞
- 二、掛起
- 三、運行R
- 四、休眠D
- 五、四個重要概念
- 總結
前言
??上篇內容大家看的云里霧里,這實在是正常不過,因為例如 寫實拷貝 等一些概念的深層原理我還沒有講解,大家不用緊張,我們繼續往下學習就行!!!
??在本篇開始之前,我們先來回顧一下有關 進程 的一些知識點:
- OS管理的本質是先描述,再組織
- OS并非直接管理進程 ,而是管理 進程 的 PCB(task_struct)
- PCB 中有著進程的各種信息,包括:PID、PPID、進程狀態等
- 我們可以通過函數 getpid() 獲取當前進程的 PID
- 進程 間存在父子關系,可以通過 fork() 主動創建 子進程
- 父子進程 相互獨立,共享一份代碼時,具有 寫時拷貝 機制
一、阻塞
??先來看看進程狀態圖
- 阻塞 就是 進程 因等待某種條件就緒,而導致的一種不推進狀態
- 通俗來說,阻塞 就是 進程 卡住了,原因就是缺少資源
??比如在我們日常生活中,常常發生堵車,這就是因為 道路資源 不夠用了,車輛這個 進程 就需要原地等待
那么 進程 需要什么資源呢?
- 比如 磁盤、網卡、顯卡 等各種外設
- 假設你現在想在 steam 上下載游戲,當你點擊下載按鈕后提示磁盤空間不足,此時是無法運行 steam下載 這個進程的,因為此 進程 需要等待足夠大的 磁盤資源
- 此時我們就稱此 進程 為 阻塞 狀態
??一言以蔽之,進程阻塞就是不被調度,原因是 進程 的 task_struct 結構體需要在某種被 OS 管理的資源下排隊
二、掛起
??理解 進程阻塞 后,理解 進程掛起 就比較輕松了
??其定義為:當 CPU 資源緊張時,將 進程 交換至 磁盤 中掛起,此時內存中只有 PCB,所以 掛起 可以看作一種特殊的阻塞狀態
??比如在我們日常生活中,一邊走路一邊玩手機很危險,所以此時我們會將玩手機這個 進程掛起 ,即把手機揣進兜里,然后 專心執行走路 這個 進程
??進程是何種狀態,取決于此進程的PCB在哪里排隊!!! 本質無外乎鏈表的增、刪、查、改!!!
三、運行R
??一個程序在運行就表示該 進程 處于 運行 狀態,那么事實真的如此嗎?
??可以看到當前的進程狀態為 睡眠 S+
注: + 表示當前進程在前臺運行中
原因在于:
- 運行了,但我們很難捕捉到
- 根據馮諾依曼體系, printf 也是將內存里面去寫的,相當于顯示器也有自己的緩存,printf 也有自己的 I/O,因為 I/O 的速度很慢,所以大部分時間都在 I/O, 所以我們進程大部分都在等待狀態
四、休眠D
??存在一種特殊睡眠狀態 休眠 D,休眠 又被稱為不可中斷休眠,顧名思義,休眠 D 狀態下的 進程 是無法終止的,kill 指令和 OS都無能為力,只能默默等待 進程阻塞 結束,拿到資源了,進程 才會停止 休眠 D 狀態
??倘若存在 休眠 D 進程長時間運行,那么此時就表示系統離宕機不遠了
??我來畫個示意圖來解釋一下為什么會有這么一個特殊的進程狀態,
??情景是 進程A 想將一整天銀行的交易記錄(100w條)永久保存到磁盤里面,進程A把磁盤叫出來,說:我這邊有100w條數據,請你幫我保存到你那邊去唄,而磁盤相對于內存來說是非常慢的,而這個時候進程A就只能阻塞了,就被鏈入到磁盤等待隊列 struct device* devices 中了,而狀態變為S(假設,事實上是D,后面就知道為什么不能了),這個時候進程A就翹腳嗑瓜子了,讓其他進程運行,但是這個時候,OS急沖沖地跑過來,說:我們內存資源已經不足了,你再占用資源我自己都要寄了,覆巢之下,豈有完卵!,我只好把你干掉了。這個時候磁盤發現寫到第80w的時候發現這個時候磁盤也要慢了,只好告訴進程A:趕快告訴用戶,寫入失敗了,趕快返回了錯誤碼。但是這個時候進程A已經被OS干掉了,磁盤只好把數據丟棄了,也就造成了數據的丟失
??數據丟失導致銀行老板把進程A、OS、磁盤叫到辦公室,磁盤委屈道:我就是個臭跑腿的,我已經將數據寫入失敗的可能告訴你了,我跟進程B,進程C都是這樣干的,這不怪我!進程A說:這不怪我,這怪OS把我給干掉了,人在家中坐,鍋從天上來,OS說:這不怪我,我本來就是管理者,我只是在履行保護內存資源的職責!
??很明顯,明察秋毫的我們發現了其實是銀行的問題,定義了一個新的狀態D深度睡眠,用于當 OS 和 磁盤 進行 I/O阻塞 的時候,這就是D狀態的由來
五、四個重要概念
??競爭性: 系統進程數目眾多,而CPU資源只有少量,甚至1個,所以進程之間是具有競爭屬性的。為了高效完成任務,更合理競爭相關資源,便有了優先級。
??獨立性: 多進程運行,需要獨享各種資源,多進程運行期間互不干擾。
??并行: 多個進程在多個CPU下分別同時進行運行,這稱之為并行。
??并發: 多個進程在一個CPU下采用進程切換的方式,在一段時間之內,讓多個進程都得以推進,稱之為并發。
??CPU執行進程代碼,不是把進程代碼執行完畢,才開始執行下一個,而是給每一個進程預分配一個 時間片 ,基于 時間片 ,進行調度輪轉(單CPU下)
總結
??這篇有點水,下篇爭取來個實的!