這是操作系統(tǒng)系列第 2 篇。
如果你想知道操作系統(tǒng)每天都在做些什么,那就打開你的資源監(jiān)視器:

資源監(jiān)視器截圖,Windows 10
單獨(dú)通過這一張圖,我們就能夠總結(jié)出操作系統(tǒng)的幾個(gè)重要功能:
- 進(jìn)程管理
- 線程管理
- 內(nèi)存管理
- I/O 管理(包含了磁盤調(diào)度)
- 文件管理,這一功能在圖里沒有表現(xiàn)出來,但我相信每個(gè)使用計(jì)算機(jī)的人都知道它。
為什么我要從進(jìn)程開始講起呢?
原因很簡(jiǎn)單,我們每天使用計(jì)算機(jī),包括手機(jī)和電腦,本質(zhì)上是使用運(yùn)行在其操作系統(tǒng)上的應(yīng)用程序。對(duì)于我們來講,操作系統(tǒng)最為直觀的功能就是進(jìn)程管理,所以,讓我們從進(jìn)程管理入手,由表及里,一步步深挖操作系統(tǒng)的本質(zhì)。
進(jìn)程是什么?
我在第一篇文章里簡(jiǎn)單提到了進(jìn)程這一概念,這里再詳細(xì)講一下,加深理解。
操作系統(tǒng)的設(shè)計(jì)從根本上來說是為了迎合用戶需求,對(duì)個(gè)人用戶來說,需求就是在一臺(tái)計(jì)算機(jī)上運(yùn)行多個(gè)應(yīng)用程序,以滿足生活和工作的需要。但應(yīng)用程序這么多,不可能讓每一個(gè)程序占用一個(gè) CPU 核心啊,因?yàn)?CPU 核心是有限的,人的需求是無限的。
所以操作系統(tǒng)就需要將無限(夸張一下)的應(yīng)用程序,分配到有限的 CPU 上去。
當(dāng)我們打開一堆程序時(shí),這些程序就會(huì)被加載到內(nèi)存上,為了讓這些運(yùn)行的程序與沒有打開的程序作區(qū)分,我們創(chuàng)造了進(jìn)程(Process)這個(gè)名詞。所以,進(jìn)程就是對(duì)運(yùn)行的程序的一種抽象,具有動(dòng)態(tài)性。進(jìn)程管理其實(shí)就是操作系統(tǒng)通過某種方式,管理我們已經(jīng)打開的程序。
注:為了簡(jiǎn)化后面的討論,我們假設(shè)所說的計(jì)算機(jī)是單核的。
進(jìn)程的狀態(tài)有哪幾種?
講到進(jìn)程,我們必然需要了解進(jìn)程狀態(tài),想要了解進(jìn)程的狀態(tài),我們就得從進(jìn)程的角度,看一看進(jìn)程的一生會(huì)發(fā)生什么。
首先,用戶打開某個(gè)應(yīng)用程序,這個(gè)程序就處于新建態(tài)(New),這個(gè)時(shí)候操作系統(tǒng)還沒有為這個(gè)程序做好準(zhǔn)備工作,這個(gè)進(jìn)程自身還沒有進(jìn)入內(nèi)存,可能還留在磁盤里。
等到這個(gè)進(jìn)程被加載進(jìn)內(nèi)存,就代表它已經(jīng)準(zhǔn)備好運(yùn)行了,但因?yàn)?CPU 資源正被別的進(jìn)程占用,它只能等待操作系統(tǒng)為它分配 CPU。這個(gè)狀態(tài)稱為就緒態(tài)(Ready)。
在就緒態(tài)一段時(shí)間后,總會(huì)分配到 CPU 資源,一旦進(jìn)程開始執(zhí)行,它就進(jìn)入了運(yùn)行態(tài)(Running)。
有的進(jìn)程可能會(huì)執(zhí)行某些阻塞操作,就拿 I/O 操作來舉例子,執(zhí)行操作后,進(jìn)程需要等待 I/O 操作完成,第一篇文章講過,進(jìn)程在這段時(shí)間內(nèi)是無法使用 CPU 的,如果讓它繼續(xù)占用 CPU,就造成了資源浪費(fèi)。所以操作系統(tǒng)會(huì)剝奪它的 CPU 使用權(quán),并把它放在阻塞態(tài)。等到 I/O 操作結(jié)束后,再將其放入就緒態(tài)。
還有最后一種狀態(tài)——退出態(tài),顧名思義,進(jìn)程終止后,就會(huì)進(jìn)入退出態(tài),這個(gè)進(jìn)程可能還沒有從內(nèi)存中清理出去。等到進(jìn)程完全退出內(nèi)存,進(jìn)程的一生就徹底結(jié)束了。
綜合以上的討論,我們得到了進(jìn)程的 5 種狀態(tài):

細(xì)心的讀者可能會(huì)發(fā)現(xiàn),運(yùn)行態(tài)到阻塞態(tài),以及阻塞態(tài)到就緒態(tài)之間的箭頭是單向的。為什么?
先來看看運(yùn)行態(tài)和阻塞態(tài)?;貞浺幌?,一個(gè)進(jìn)程處于阻塞態(tài)代表什么?(希望你看到這確實(shí)停下來思考了)
一個(gè)進(jìn)程處于阻塞態(tài),代表進(jìn)程執(zhí)行了某個(gè)阻塞操作,正在等待操作的結(jié)果。也就是說,處于阻塞態(tài)的進(jìn)程沒有使用 CPU 的能力,所以即使給了它 CPU 它也沒辦法運(yùn)行,自然無法進(jìn)入執(zhí)行狀態(tài)。所以從阻塞態(tài)是無法直接跳到運(yùn)行態(tài)的。
再來說說就緒態(tài)和阻塞態(tài)。如果一個(gè)進(jìn)程位于就緒態(tài),說明它現(xiàn)在沒有使用 CPU,所以更不可能執(zhí)行阻塞操作。因此從就緒態(tài)也不能直接跳轉(zhuǎn)到阻塞態(tài)。
結(jié)合剛剛的解釋,我們來看看一個(gè)簡(jiǎn)單的進(jìn)程的排隊(duì)模型:

圖中的 ABCDEF 代表了進(jìn)程
要注意的是,就緒態(tài),運(yùn)行態(tài)和阻塞態(tài)提供了一種描述進(jìn)程行為的系統(tǒng)方法,指導(dǎo)了操作系統(tǒng)的實(shí)現(xiàn),許多實(shí)際的操作系統(tǒng)都是按照這樣的三種狀態(tài)進(jìn)行具體構(gòu)造的。但這不代表就沒有其他狀態(tài)的立足之地了,在一些實(shí)現(xiàn)中(其實(shí)是主流實(shí)現(xiàn),但由于牽扯到虛擬內(nèi)存的概念,所以留到以后講解),還有掛起態(tài)等狀態(tài)。但不管哪種狀態(tài),他們都是為了操作系統(tǒng)能夠最大化利用計(jì)算機(jī)資源而抽象出來的。
留幾個(gè)小問題做思考:
- 為什么只有從運(yùn)行態(tài)才能轉(zhuǎn)換到退出態(tài)?
- 你能看懂上圖排隊(duì)模型嗎?
PCB 是什么東西?
操作系統(tǒng)在管理和控制進(jìn)程的時(shí)候,首先必須知道進(jìn)程的位置(即進(jìn)程被加載到哪一塊內(nèi)存了),其次,它還需要知道進(jìn)程的屬性,如進(jìn)程 ID,進(jìn)程狀態(tài)等,所以我們就得有一個(gè)結(jié)構(gòu)能夠保存這些信息。
進(jìn)程控制塊(Process Control Block)就是這么一個(gè)結(jié)構(gòu)。進(jìn)程控制塊會(huì)在程序啟動(dòng)時(shí)就被創(chuàng)建出來。

進(jìn)程控制塊的主要內(nèi)容及內(nèi)存映像(字丑勿怪)
我們可以看到,PCB 中存儲(chǔ)著進(jìn)程 ID,寄存器狀態(tài),棧指針等重要信息,這些信息現(xiàn)在看來非常陌生,但以后隨著你對(duì)操作系統(tǒng)理解的加深,你就會(huì)理解這些信息的含義和作用。
圖中還有一個(gè)信息,那就是 PCB 存儲(chǔ)在內(nèi)核空間——表明只有操作系統(tǒng)有權(quán)利更改 PCB 里面的內(nèi)容。因?yàn)?PCB 太重要了,如果其內(nèi)部信息被惡意修改,將造成進(jìn)程意外終止,甚至可能導(dǎo)致操作系統(tǒng)的崩潰。
總結(jié)
讓我們來串一下今天的內(nèi)容:
如果一個(gè)程序開始運(yùn)行,那么操作系統(tǒng)就會(huì)為其創(chuàng)建一個(gè)進(jìn)程控制塊,并將其加載到內(nèi)存中,進(jìn)程控制塊內(nèi)的「進(jìn)程狀態(tài)」信息會(huì)更改為就緒態(tài),并將進(jìn)程放入就緒隊(duì)列等待分配 CPU。一旦分得 CPU,進(jìn)程就進(jìn)入運(yùn)行態(tài),根據(jù)實(shí)際情況,還可能因?yàn)閳?zhí)行阻塞操作而進(jìn)入阻塞態(tài),等到程序運(yùn)行完畢,進(jìn)程就被操作系統(tǒng)清出內(nèi)存,然后刪除其進(jìn)程控制塊。
如果看完上一段,對(duì)黑體字的概念還很模糊,那我建議你再慢慢看一遍文章,而且一定要帶上自己的思考,沒有經(jīng)過思考的閱讀的效率是很低的。
希望你在看完文章之后有所收獲。感謝你的閱讀,我們后會(huì)有期!
聲明:原創(chuàng)文章,未經(jīng)授權(quán),禁止轉(zhuǎn)載