目錄
1 引言?
2?操作系統的資源分配
3進程狀態
3.1運行狀態
3.2 阻塞狀態
3.3掛起狀態
?4.進程狀態詳解
4.1 運行狀態R
4.2 休眠狀態S
4.3深度睡眠狀態D
4.4僵尸狀態Z?
5 孤兒進程
6?進程優先級??
?其他概念
1 引言?
🌻在前面的文章中,我們已經介紹了進程的概念,和如何取獲取進程相關的屬性及進程相關性的信息,以及如何去創建一個子進程。可是我們知道,系統中的內存資源是非常寶貴的,且系統中存在著大量的進程,對于這些進程,系統需要給其分配所需要的資源,對于如今的單核或者多核的計算機,想象一下,如果大量的進程同時需要進行處理,那么會產生什么樣子的后果呢?
? ? ? ?所以為了整個操作系統的穩定和效率,操作系統會對進程進行調度、管理,于是就需要對進程狀態進行分類,操作系統需要知道哪些進程是可運行的,以便將它們分配給可用的CPU核心;哪些進程是睡眠的,這樣可以將他們的內存頁面換出到磁盤,釋放內存資源等。
2?操作系統的資源分配
? 為了理解進程狀態的概念,我們需要先理解一些操作系統進行資源分配的概念。
- 根據馮諾依曼體系結構,操作系統的設計就是向下為了與硬件交互,管理所有的軟硬件資源,向上為用戶提供一個良好的執行環境。那操作系統是怎么管理所有的硬件資源的呢?類似對進程的管理,操作系統會為每一個硬件維護了一個數據結構,用來存儲他們的屬性及相關信息。
- 而在描述每一個硬件的結構體中,一般都會存在一個用于給進程分配資源的等待隊列。
- 當進程在執行中需要訪問硬件設備時,即需要占用硬件設備資源的時候,操作系統就會將CPU隊列中該進程的PCB拿出來放在該硬件的分配資源的等待隊列中。
- 在硬件的分配資源等待的隊列中,總是遵循先進先出的規則,硬件會給每一個在隊列中排到隊的進程分配資源,并不是只要在這個隊列中就立即分配資源。
- 多個進程在一個CPU下采用進程切換的方式,在一段時間之內,讓多個進程都得以推進,稱之為并發
3進程狀態
🌸在正式介紹進程狀態之前,我們先說幾個概念以助于理解進程狀態:?
- 一個CPU一個運行隊列
- 讓進程入隊列的本質就是將該進程的task_struct結構體對象放入隊列中
- 進程不止會等待(占用)CPU資源,也可能隨時隨地需要外設資源
- 所謂的進程的不同的狀態,本質上是進程在不同的隊列中等待資源
3.1運行狀態
進程的運行狀態并不是進程正在運行就叫運行狀態,而是系統將進程的PCB放到CPU的分配資源的隊列中等待運行的狀態叫做運行態,無論進程是在排隊還是在占用CPU資源。
3.2 阻塞狀態
正在執行的進程由于發生某事件(如外設請求?)暫時無法繼續執行,此時引起進程調度,操作系統會把需要與外設進行交互的進程拿出來與外設進行交互,把另一個進程放進cpu運行隊列中,一般將這種狀態稱為阻塞狀態。
3.3掛起狀態
進程=PCB(內核數據結構)+磁盤中的代碼
當一個程序運行的時候,程序的代碼和數據會被加載到內存中,會占用內存的資源。對于系統中的一些短時間內不會被調度或者處于阻塞狀態的進程,這些代碼短時間內不會被運行起來,但是這些進程的代碼和數據仍然在內存中,當內存空間不夠時,操作系統會將這類進程暫時調離出內存,也就是將這類進程的程序和代碼數據從內存中拿出來,放到指定的磁盤空間中,而將進程的PCB留在內存中。這樣的操作稱為進程的掛起。當之后條件允許的時候,這些代碼和數據會被操作系統再次調回內存。
🌻掛起狀態和阻塞狀態的比較
相同點:1). 進程都暫停運行
? ? ? ? ? ? ? ?2).?進程都釋放CPU,即兩個過程都會涉及到上下文的切換
不同點: 1).?對系統資源的占用:雖然都釋放了CPU,但阻塞的進程仍處于內存中,而掛起的進程的代碼和數據都已經被放入了磁盤。
?4.進程狀態詳解
上述狀態 是在宏觀操作系統的層面上敘說狀態,不同操作系統會有不同說法,接下來我們將演示一下Linux 操作系統的進程狀態以及具體演示。如下是Linux 操作系統的不同狀態。
4.1 運行狀態R
我們寫一個myprocess.c 的程序,其中是個循環,一直執行下去。
通過命令 ps ajx | head -1 && ps ajx | grep myprocess? 命令我們可以看到當前進程狀態。
通過上圖我們能看到? STAT:R+ 即狀態是運行狀態。?(關于+后續說明)
4.2 休眠狀態S
我們對myprocess.c 的程序進行改寫,其中也是個死循環,一直執行下去,唯一不同的是我們進行了打印。
通過命令 ps ajx | head -1 && ps ajx | grep myprocess? 看到當前進程狀態。
我們發現當前狀態STAT: S+,程序一直運行下去,不停的輸出a的值為:4,進程的狀態不應該是R+嗎?
?當cpu 運行myprocess 程序時速度是極快的,但是這里我們使用了printf()函數,即把數據打印在顯示器上,所以這個進程需要與顯示器進行交互,而與顯示器交互的時間相比于cpu運行時間要長很多,所以此時操作系統會把myprocess這個進程從cpu的運行隊列中拿出,去與外設顯示器交互,然后再放到cpu運行隊列中運行,所以說雖然這個進程一直在運行,但大多數時間都在與外設交互所以進程的狀態是S狀態。
4.3深度睡眠狀態D
深度睡眠狀態是不可中斷的狀態,是阻塞狀態的一種,disk sleeping,說明該睡眠狀態是跟dis(磁盤有關),指的是進程在等待磁盤資源時的阻塞狀態。為什么有了睡眠狀態S還要有一個深度睡眠狀態D呢? 以及為什么深度睡眠狀態要是不可中斷的狀態。
?當我們需要輸入一個很大的用戶信息文件時候,需要向磁盤中傳輸數據,此時這個進程會在內存中與磁盤進行長時間的交互,即阻塞狀態,當操作系統的內存空間不足的時候會進行掛起狀態,但所掛起狀態仍然內存資源不足的時候,系統會把這塊內存釋放掉,那么此時用戶信息就會丟失,所以Linux操作系統有個深度休眠狀態D,即不可中斷狀態。?
4.4僵尸狀態Z?
Linux系統中的 X 狀態,就是概念中的死亡狀態,上面已經提到過當進程不會被調度、不會運行時,就會進入終止狀態,此時該進程就等著被系統釋放了。但是在Linux中,當進程不會再調度、不會再運行時,不會立馬進入X狀態,而是先進入Z(僵尸狀態),此進程被稱為僵尸進程Z
僵尸進程 Z的感性認識:進程被創建出來------->完成任務----------->要知道它完成的如何,可以不關心結果(進程退出的時候,不能立即被釋放進程對應的資源,而是保存一段時間,讓父進程或os來進行讀取)------------------>進程進入死亡狀態X被系統回收。
這里我們創建了一個子進程,子進程在5秒之后退出程序,但是父進程仍然會執行while循環,也就是說這個程序并沒有終止,所以盡管子進程退出了但是因為這個程序還在運行,操作系統并沒有對其釋放,所以子進程將會是僵尸狀態。?
??
從上圖我們可以看出剛開始子進程的狀態是S+,即與顯示器進行交互,后面子進程退出,但父進程還在執行,所以操作系統還沒有對其回收,此時子進程的狀態就為僵尸進程Z。
當我們終止進程的時候再進行查看狀態的時候已經查不到了,因為進程被系統釋放掉了
僵尸進程的危害:
- 進程的退出狀態必須被維持下去,因為他要告訴關心它的進程(父進程),你交給我的任務,我辦的怎 么樣了。可父進程如果一直不讀取,那子進程就一直處于Z狀態。
- ?維護退出狀態本身就是要用數據維護,也屬于進程基本信息,所以保存在task_struct(PCB)中,換句話 說,Z狀態一直不退出,PCB一直都要維護。?那一個父進程創建了很多子進程,就是不回收,就會造成內存資源的浪費。因為數據結構對象本身就要占用內存
- 僵尸進程一直不被釋放將會造成內存泄漏。
5 孤兒進程
- 父進程如果提前退出,那么子進程后退出,進入Z之后,那該如何處理呢?
- 父進程先退出,子進程就稱之為“孤兒進程”
- 孤兒進程被1號init進程領養,1號init進程回收(1號int進程不是別的就是bash).
我們寫個程序演示孤兒進程
???????
?我們能夠看到父進程PID為18214?
這一步我們把父進程18214 kill掉,明顯能夠看出子進程18215的父進程變成1而 1就是bash.,并且我們可以看到此時子進程被1進行收養之后,狀態變成S,沒有了+,這里的“+”表示是前臺運行的意思,當子進程被1號領養之后,其狀態就變為了后臺運行。?
?此時子進程被1號進程領養之后,變成后臺進程,用Ctrl + x并不能退出進程了,只能用kill + PID 殺死進程。
小結:
- 這種現象一定存在
- 子進程會被操作系統領養
- 為什么要這樣做,如果不領養,那么子進程退出時,對于的僵尸,便沒有人回收了。
- 被領養的進程-------------->孤兒進程
- 如果前臺進程創建的子進程變成孤兒了,會自動變成后臺進程。
6?進程優先級??
進程優先級是什么?為什么需要有進程優先級?
進程優先級也是進程的一種屬性,同樣被包含在task_struct結構體中,其代表了CPU資源分配的先后順序,優先權高的進程擁有優先執行的權利。
我們系統的資源是非常有限的,當出現大量的進程時,面對少量資源就不可避免地出現資源競爭的情況,類似現實生活中,如果系統不干預這種情況,任由進程自己競爭,則會出現部分進程執行不了自己的任務的情況,所以系統需要確定一個優先級,配置進程優先權對多任務環境的Linux很有用。
ps -l ps -al 可以查看進程的優先級PRI(priority優先級)NI(nice).Linux系統默認優先級為80
最終優先級 =老的優先級+nice.
Linux支持進程運行時,進行優先級調整,調整的策略就是更改nice完成。
知道進程的PID時, 進入top, 再按r, 再輸入PID, 再輸入需要的NI值, 就可以做到NI值的修改(必須為root用戶)
- 不同程序界面的PRI值是不同的,可能是因為基準不同
- NI值是有自己的限度的,取值范圍為-20到19
?其他概念
- ?競爭性: 系統進程數目眾多,而CPU資源只有少量,甚至1個,所以進程之間是具有競爭屬性的。為了高 效完成任務,更合理競爭相關資源,便具有了優先級
- ?獨立性: 多進程運行,需要獨享各種資源,多進程運行期間互不干擾
- ?并行: 多個進程在多個CPU下分別,同時進行運行,這稱之為并行
- ?并發: 多個進程在一個CPU下采用進程切換的方式,在一段時間之內,讓多個進程都得以推進,稱之為 并發。