黃驊烈士網(wǎng)奇seo培訓官網(wǎng)
文章目錄
- 前言
- 一、初識fork
- 1.演示
- 2.介紹
- 3.將子進程與父進程執(zhí)行的任務(wù)分離
- 4.多進程并行
- 二、進程的狀態(tài)
- 1.進程的狀態(tài)都有哪些?
- 2.查看進程的狀態(tài)
- 2.運行(R)
- 3.阻塞
- 4.僵尸進程(Z)
- 1.僵尸狀態(tài)概念
- 2.為什么要有僵尸狀態(tài)?
- 3.僵尸狀態(tài)的例子
- 3.僵尸狀態(tài)的危害
- 5.孤兒進程
- 三、進程的優(yōu)先級
- 1.優(yōu)先級概念
- 1.權(quán)限與優(yōu)先級
- 2.什么是優(yōu)先級
- 3.為什么存在優(yōu)先級
- 4.特性
- 2.查看系統(tǒng)進程
- 3.PRI和NI
- 4.修改進程的優(yōu)先級
- 總結(jié)
前言
本文介紹了創(chuàng)建進程、查看進程、進程的狀態(tài)以及進程的優(yōu)先級相等關(guān)概念
一、初識fork
通過系統(tǒng)調(diào)用fork創(chuàng)建子進程。
1.演示
文件test.c
運行結(jié)果:
2.介紹
fork的頭文件為unistd.h
fork的返回值:父進程會返回子進程的pid,子進程返回0(一個子進程只有一個父進程,但是有個父進程可以有無數(shù)個子進程,一次要將子進程的pid返回給父進程,而子進程不需要)
3.將子進程與父進程執(zhí)行的任務(wù)分離
根據(jù)父子進程的返回值不同:
文件test.c
運行結(jié)果:
4.多進程并行
文件test.c
運行結(jié)果:
二、進程的狀態(tài)
1.進程的狀態(tài)都有哪些?
進程的狀態(tài)有很多:運行、就緒、掛起、阻塞等等。
進程有這么多不同的狀態(tài),本質(zhì)上是為了滿足不同的運行場景。
具體的進程狀態(tài):
static const char * const task_state_array[] = {
"R (running)", /* 0 */
"S (sleeping)", /* 1 */
"D (disk sleep)", /* 2 */
"T (stopped)", /* 4 */
"t (tracing stop)", /* 8 */
"X (dead)", /* 16 */
"Z (zombie)", /* 32 */
};
-
R運行狀態(tài)(running):并不意味著進程一定在運行狀態(tài),他只是表明進程在運行隊列里。
-
S睡眠狀態(tài)(sleeping):意味著進程正在等待時間完成(這里的睡眠也成為可中斷睡眠/淺度睡眠(interruptible sleep))。
例子:進程從運行到訪問外設(shè)再到訪問外設(shè)完畢這段時間進程處于睡眠狀態(tài)。 -
D磁盤休眠狀態(tài)(Disk sleep):也叫做不可中斷睡眠狀態(tài),該狀態(tài)的進程通常會等待I/O的結(jié)束。該進程不能被操作系統(tǒng)kill掉。
例子:某一個進程向磁盤發(fā)布了寫東西的任務(wù)(例如:要求寫0~100到文件上),那么磁盤就會去完成這個任務(wù),此時進程處于等待狀態(tài)。如果恰好操作系統(tǒng)內(nèi)的資源緊缺,操作系統(tǒng)有權(quán)利自主殺掉一些不干事情的進程(未處于運行狀態(tài)),該進程就會被操作系統(tǒng)殺死。由于外設(shè)的運行速度很慢,等到外設(shè)完成任務(wù)回來尋找對應(yīng)的進程交代任務(wù)結(jié)果時,發(fā)現(xiàn)該進程無法被喚醒(該進程已經(jīng)被殺死了),這就會導(dǎo)致磁盤內(nèi)對應(yīng)數(shù)據(jù)的丟失。因此,為了避免這種情況出現(xiàn),我們將一些特殊的進程賦予D狀態(tài)(相當于免死金牌,避免操作系統(tǒng)將它殺死),這樣它只能等對應(yīng)的I/O完成才會重新變?yōu)槠渌麪顟B(tài)。 -
T停止狀態(tài)(stopped):可以通過發(fā)送SIGSTOP信號給進程來停止進程(該進程處于T狀態(tài)),然后可以給這個被暫停的狀態(tài)發(fā)送SIGCONT信號,讓該進程繼續(xù)運行(當一個前臺進程被暫停后,又被恢復(fù)繼續(xù)運行時,前臺進程會轉(zhuǎn)為后臺進程,此時進程無法被ctrl + c終止,只能用kill -9 (進程pid)終止進程)。
-
X死亡狀態(tài)(dead):該狀態(tài)只是一個返回狀態(tài),不會在任務(wù)列表中看到這個狀態(tài)。
-
還有兩個特殊的狀態(tài):僵尸狀態(tài)和孤兒狀態(tài)在后續(xù)內(nèi)容會詳細講解。
2.查看進程的狀態(tài)
ps aux
或者 ps ajx
命令可以查看進程的狀態(tài)。
2.運行(R)
- 一個CPU一個運行時隊列;
- 讓進程進入運行時隊列,本質(zhì)是將該進程的task_struct結(jié)構(gòu)體放入運行隊列中;
- 進程PCB在runqueue時,該進程就是運行狀態(tài)(R),而不是該進程在運行時才算;(CPU很快,可以將運行隊列中的進程很快的過一遍,因此運行隊列里都是處于運行狀態(tài))
狀態(tài) ->進程內(nèi)部的屬性 -> task_struct -> int(1:run ; 2:run ; 3:run ; 4:run),進程的狀態(tài)本質(zhì)就是進程PCB中的一個整型值。 - 不要以為只有CPU會被多進程訪問,硬件設(shè)備也是稀缺資源,也會被多進程訪問。
- 所謂的進程的不同狀態(tài),本質(zhì)是進程在不同的隊列中等待某種資源(將task_struct結(jié)構(gòu)體對象放入不同的的等待隊列)。
3.阻塞
- 外設(shè)硬件的訪問速度是很慢的(相對CPU),但是進程或多或少都需要訪問它,但是在多進程同時訪問硬件設(shè)備時,也只有少量的進程(競爭力強的)可以訪問到它。
- 當有其他進程在訪問該設(shè)備時,其他進程只能等待。等待中的進程將從運行時隊列中取出,放入該設(shè)備對應(yīng)的阻塞(等待)隊列中,此時該進程處于阻塞狀態(tài)。
- 等到設(shè)備空余出來(沒有進程訪問的時候),OS會知道它好了,然后OS就會等待的該進程的狀態(tài)由阻塞改為運行(R),在將該進程放入運行時隊列即可機械運行。
4.僵尸進程(Z)
1.僵尸狀態(tài)概念
一個小栗子
一天,張三在路上跑步,突然路邊有一個人死亡了,張三立刻打電話給警察局,那么在這個路人死亡的那一瞬間直到警察查明他的信息以及死亡原因的這一過程就相當于處于僵尸狀態(tài)(死了,但是別人不知道他死了)。
- 當子進程退出,但是父進程沒有(通過
wait()
系統(tǒng)調(diào)用)讀取子進程的退出狀態(tài)代碼時,就會導(dǎo)致子進程處于僵尸狀態(tài)。 - 僵尸進程會議終止狀態(tài)保持在進程表中,并且一直等待父進程讀取退出狀態(tài)代碼。
- 因此,只要子進程退出,父進程還在勻稱并且沒有讀取子進程的狀態(tài),子進程就進入僵尸狀態(tài)。
2.為什么要有僵尸狀態(tài)?
進程被創(chuàng)建是為了完成分配給他的任務(wù),當然生活中有些事情需要返回結(jié)果,有些事情不需要,但是作為一個程序它無論你需不需要知道結(jié)果,它都得將任務(wù)的執(zhí)行情況返回。程序退出時不能立即釋放程序中的所有資源,而是需要保持一段時間,讓父進程/OS讀取它的退出代碼。
退出程序和釋放程序的資源之間的一段時間程序是處于僵尸狀態(tài)(注意:僵尸狀態(tài)是一個問題),進程推出時沒有立即回收它的退出代碼。
3.僵尸狀態(tài)的例子
創(chuàng)建一個子進程,讓父進程不要退出,并且什么也不干(不回收子進程),讓子進程退出(exit(0)
頭文件是stdlib.h
),這時子進程就處于僵尸狀態(tài)。
3.僵尸狀態(tài)的危害
- 進程的退出狀態(tài)必須被維持下去,因為他要告訴它的父進程(或者0S),你交給我的任務(wù),我辦的怎么樣了(即,結(jié)果如何)。如果父進程一直不讀取,子進程就會一直處于Z狀態(tài)。
- 維持退出狀態(tài)本身也是需要數(shù)據(jù)維護的,也屬于進程的基本信息,因此它是保存在task_struct(PCB)中的。當然,如果Z狀態(tài)一直不退出,該PCB就要一直被維護。
- 如果推廣父進程創(chuàng)建了很多子進程,但是不回收,是不是就會造成內(nèi)存資源的浪費(內(nèi)存泄漏)?
數(shù)據(jù)結(jié)構(gòu)對象本身就要占內(nèi)存(C中定義一個結(jié)構(gòu)體變量/對象,是需要在內(nèi)存的某個位置開辟空間的)
5.孤兒進程
那么問題來了,如果父進程先退出,子進程再退出進入Z狀態(tài)后,又該怎么辦呢?
- 父進程先退出的話,它的子進程就被稱為“孤兒進程”。
- 孤兒進程會被操作系統(tǒng)的1號init進程領(lǐng)養(yǎng),它的資源由init進程回收。
三、進程的優(yōu)先級
1.優(yōu)先級概念
1.權(quán)限與優(yōu)先級
權(quán)限是限制是否可以做某事,優(yōu)先級是限制做某事的順序(先做還是后做)。
2.什么是優(yōu)先級
- 獲得某個資源的順序(是先獲得該資源還是后獲得該資源)。
- 優(yōu)先級和進程的狀態(tài)一樣本質(zhì)是是進程PCB中的一個(或幾個)整型數(shù)字,Linux中的優(yōu)先級是用兩個整型數(shù)表示的。
3.為什么存在優(yōu)先級
因為資源是有限的,但是有很多進程都想申請資源。
4.特性
- 競爭性:
系統(tǒng)的進程眾多,但是CPU資源只有少量(甚至只有一個),所以進程之間是具有競爭屬性的。為了高效完成任務(wù),更加合理的競爭相關(guān)的資源,便具有了優(yōu)先級。 - 獨立性:
多進程運行需要獨享各種資源,多進程運行期間互不干擾。 - 并行:
多個進程在多個CPU下,同時進行運行,這稱之為并行。 - 并發(fā):
多個進程在單個CPU下采用進程切換(CPU采用輪轉(zhuǎn)的方式,給每個進程一定的時間片運行,進行進程切換)的方式,在一段時間內(nèi)多個進程一同推進,稱之為并發(fā)。
2.查看系統(tǒng)進程
在Linux/Unix系統(tǒng)中,用ps -la
命令可以查看進程的信息。
UID:該代表執(zhí)行者的身份
PID:該進程的代號
PPID:該進程是由哪個進程發(fā)展衍生來的(即該進程的父進程的PID)
PRI:該進程可被執(zhí)行的優(yōu)先級
NI:該進程的nice值
3.PRI和NI
- PRI:進程的優(yōu)先級,該值越小優(yōu)先級越高;
- NI:進程的nice值,表示進程可以被執(zhí)行的優(yōu)先級的修正數(shù)值(調(diào)節(jié)進程優(yōu)先級)
- PRI(new) = PRI(old)+ NI;
- 當nice值為負值時,該進程的優(yōu)先級值會變小,優(yōu)先級會變高,越快被執(zhí)行;
- nice的取值范圍為-20到19,總共40個級別。
4.修改進程的優(yōu)先級
在Linux中修改進程的優(yōu)先級是通過修改PRI和NI。也就是說,進程的優(yōu)先級是受到nice值的影響的,但是默認情況下nice值為0.
新的優(yōu)先級 = 老的優(yōu)先級 + NI
注意:老的優(yōu)先級指80(即,一旦要修改進程的優(yōu)先級,無論它之前的優(yōu)先級為多少都將老的優(yōu)先級設(shè)置為80!),其中NI是nice值,他的取值范圍為[-20,19],這意味著優(yōu)先級是有取值范圍的[80 - 20,80 + 19]。
修改進程的優(yōu)先級,就是修改nice值。
命令是:
sudo top
- 步驟1:
sudo top
- 步驟2:進入top后,輸入r然后輸入進程的pid(進入該進程),輸入要修改的nice值。
注意:調(diào)整進程的優(yōu)先級不代表可以隨意調(diào)整,這種做法是操作系統(tǒng)不允許的,會導(dǎo)致調(diào)度失衡,因此有一定的取值范圍。
總結(jié)
以上就是今天要講的內(nèi)容,本文介紹了創(chuàng)建進程、查看進程、進程的狀態(tài)以及進程的優(yōu)先級相等關(guān)概念。本文作者目前也是正在學習C++相關(guān)的知識,如果文章中的內(nèi)容有錯誤或者不嚴謹?shù)牟糠?#xff0c;歡迎大家在評論區(qū)指出,也歡迎大家在評論區(qū)提問、交流。
最后,如果本篇文章對你有所啟發(fā)的話,希望可以多多支持作者,謝謝大家!