Linux下的進(jìn)程和進(jìn)程間的狀態(tài)轉(zhuǎn)換。在我們的計(jì)算機(jī)層次結(jié)構(gòu)中,操作系統(tǒng)是處于一個(gè)承上啟下的層次。如下圖~
在計(jì)算機(jī)中,操作系統(tǒng)的定位是一個(gè)管理者,對(duì)上管理在系統(tǒng)中運(yùn)行的進(jìn)程,對(duì)下通過驅(qū)動(dòng)程序管理各種硬件。
說到進(jìn)程,首先得稍微解釋一下,什么叫做程序。
程序:程序是以某種語(yǔ)言編寫,為完成某個(gè)特定任務(wù)的一系列指令和數(shù)據(jù)的有序集被稱之為程序。
那么什么是進(jìn)程?
從用戶的角度來(lái)解讀,進(jìn)程就是程序的一次動(dòng)態(tài)的執(zhí)行過程。
但是想要深入理解進(jìn)程的概念,一定要知道操作系統(tǒng)是怎么解讀進(jìn)程的。
首先要了解進(jìn)程控制塊(Process Control Block),簡(jiǎn)稱PCB。進(jìn)程屬性的集合全部被放在PCB之中,在Linux下,PCB是一個(gè)叫做task_struct的結(jié)構(gòu)體之中。
學(xué)過C數(shù)據(jù)結(jié)構(gòu)的同學(xué)應(yīng)該都知道,結(jié)構(gòu)體用來(lái)描述一個(gè)結(jié)構(gòu)的信息,通過指針我們把這些結(jié)構(gòu)組織起來(lái),形成不同的數(shù)據(jù)結(jié)構(gòu)。比如鏈表,二叉樹,堆等等。
而操作系統(tǒng)也是通過這樣的方式對(duì)我們的PCB來(lái)進(jìn)行管理的。
那么操作系統(tǒng)通過PCB來(lái)對(duì)進(jìn)程進(jìn)行管理,那么PCB中大概有什么關(guān)鍵信息呢?
進(jìn)程標(biāo)識(shí)符,進(jìn)程狀態(tài),進(jìn)程優(yōu)先級(jí),程序入口地址,各種計(jì)時(shí)信息,文件系統(tǒng)的相關(guān)信息,現(xiàn)場(chǎng)保護(hù)信息等等一系列的信息。
在Linux下,進(jìn)程標(biāo)識(shí)符就是pid,這個(gè)可以通過命令來(lái)獲取,也可以通過一些系統(tǒng)調(diào)用接口來(lái)獲取,如ps命令,getpid()接口。pid是在操作系統(tǒng)下唯一標(biāo)識(shí)一個(gè)進(jìn)程存在的標(biāo)識(shí)符,用于區(qū)別其他進(jìn)程,同樣的道理,一個(gè)PCB也只唯一標(biāo)識(shí)一個(gè)進(jìn)程。
在Linux下,一個(gè)進(jìn)程可以有七種不同的狀態(tài)。
R運(yùn)行狀態(tài)(running):并不意味著進(jìn)程一定在運(yùn)行中,它表明進(jìn)程要么是在運(yùn)行要么是在運(yùn)行隊(duì)列里。
S睡眠狀態(tài)(sleeping):意味著進(jìn)程在等待事件完成(可中斷睡眠)。
D磁盤休眠狀態(tài)(Disk sleep):也叫不可中斷睡眠狀態(tài),在這個(gè)狀態(tài)進(jìn)程通常會(huì)等待IO的結(jié)束。
T停止?fàn)顟B(tài)(stopped):可以通過發(fā)送SIGSTOP信號(hào)給進(jìn)程來(lái)停止(T)進(jìn)程。這個(gè)暫停的進(jìn)程可以通過發(fā)送SIGCONT信號(hào)讓進(jìn)程繼續(xù)運(yùn)行(關(guān)于信號(hào)后面還會(huì)繼續(xù)更新到相關(guān)內(nèi)容)。
X死亡狀態(tài)(dead):這個(gè)狀態(tài)只是一個(gè)返回狀態(tài),你不會(huì)在任務(wù)列表里看到這個(gè)狀態(tài)。
還有t(tracing stop)跟蹤狀態(tài)和Z(zombie)僵尸狀態(tài)。
僵尸狀態(tài)是進(jìn)程已經(jīng)終止,但是還占用這系統(tǒng)中的資源沒有釋放,這種狀態(tài)對(duì)系統(tǒng)是有害的。
僵尸進(jìn)程這種狀態(tài)比較特殊。當(dāng)進(jìn)程退出并且父進(jìn)程沒有讀取到子進(jìn)程退出的返回代碼就會(huì)產(chǎn)生僵尸進(jìn)程。
所以,只要子進(jìn)程推遲,父進(jìn)程還在運(yùn)行,但父進(jìn)程沒有讀取子進(jìn)程的狀態(tài),子進(jìn)程進(jìn)入Z狀態(tài)。
用這段小程序在Linux系統(tǒng)下運(yùn)行,然后用查看進(jìn)程狀態(tài)的命令查看就可以看到進(jìn)程變成了Z狀態(tài)。
#include #include #include int main() { pid_t id = fork(); if(id == -1){ perror("fork"); return 1; } else if(id == 0){ printf("child pid: %dn",getpid()); sleep(3); exit(0); }else{ printf("parents pid:%dn",getpid()); sleep(30); exit(EXIT_SUCCESS); } return 0; }
狀態(tài)之間的轉(zhuǎn)換關(guān)系如下:
孤兒進(jìn)程:父進(jìn)程先退出,子進(jìn)程就被稱為孤兒進(jìn)程。父進(jìn)程如果提前退出,那么子進(jìn)程后退出,進(jìn)入Z之后,該怎么辦呢?這個(gè)時(shí)候會(huì)產(chǎn)生對(duì)系統(tǒng)資源的浪費(fèi)的僵尸進(jìn)程。操作系統(tǒng)當(dāng)然不會(huì)眼睜睜的看著這種事情發(fā)生,所以當(dāng)系統(tǒng)中產(chǎn)生孤兒進(jìn)程,就會(huì)被1號(hào)init進(jìn)程領(lǐng)養(yǎng),當(dāng)然會(huì)被init進(jìn)程回收,這里的init進(jìn)程可以先理解為操作系統(tǒng)的進(jìn)程。