亚洲韩日午夜视频,欧美日韩在线精品一区二区三区,韩国超清无码一区二区三区,亚洲国产成人影院播放,久草新在线,在线看片AV色

您好,歡迎來到思海網(wǎng)絡(luò),我們將竭誠為您提供優(yōu)質(zhì)的服務(wù)! 誠征網(wǎng)絡(luò)推廣 | 網(wǎng)站備案 | 幫助中心 | 軟件下載 | 購買流程 | 付款方式 | 聯(lián)系我們 [ 會員登錄/注冊 ]
促銷推廣
客服中心
業(yè)務(wù)咨詢
有事點擊這里…  531199185
有事點擊這里…  61352289
點擊這里給我發(fā)消息  81721488
有事點擊這里…  376585780
有事點擊這里…  872642803
有事點擊這里…  459248018
有事點擊這里…  61352288
有事點擊這里…  380791050
技術(shù)支持
有事點擊這里…  714236853
有事點擊這里…  719304487
有事點擊這里…  1208894568
有事點擊這里…  61352289
在線客服
有事點擊這里…  531199185
有事點擊這里…  61352288
有事點擊這里…  983054746
有事點擊這里…  893984210
當(dāng)前位置:首頁 >> 技術(shù)文章 >> 文章瀏覽
技術(shù)文章

Centos進程狀態(tài)詳解

添加時間:2019-7-4 14:43:22  添加: 思海網(wǎng)絡(luò) 
眾所周知,現(xiàn)在的分時操作系統(tǒng)能夠在一個CPU上運行多個程序,讓這些程序表面上看起來是在同時運行的。linux就是這樣的一個操作系統(tǒng)。

在linux系統(tǒng)中,每個被運行的程序?qū)嵗龑?yīng)一個或多個進程。linux內(nèi)核需要對這些進程進行管理,以使它們在系統(tǒng)中“同時”運行。linux內(nèi)核對進程的這種管理分兩個方面:進程狀態(tài)管理,和進程調(diào)度。

進程狀態(tài)

在linux下,通過ps命令我們能夠查看到系統(tǒng)中存在的進程,以及它們的狀態(tài):

R (TASK_RUNNING),可執(zhí)行狀態(tài)。

只有在該狀態(tài)的進程才可能在CPU上運行。而同一時刻可能有多個進程處于可執(zhí)行狀態(tài),這些進程的task_struct結(jié)構(gòu)(進程控制塊)被放入對應(yīng)CPU的可執(zhí)行隊列中(一個進程最多只能出現(xiàn)在一個CPU的可執(zhí)行隊列中)。進程調(diào)度器的任務(wù)就是從各個CPU的可執(zhí)行隊列中分別選擇一個進程在該CPU上運行。

只要可執(zhí)行隊列不為空,其對應(yīng)的CPU就不能偷懶,就要執(zhí)行其中某個進程。一般稱此時的CPU“忙碌”。對應(yīng)的,CPU“空閑”就是指其對應(yīng)的可執(zhí)行隊列為空,以致于CPU無事可做。

有人問,為什么死循環(huán)程序會導(dǎo)致CPU占用高呢?因為死循環(huán)程序基本上總是處于TASK_RUNNING狀態(tài)(進程處于可執(zhí)行隊列中)。除非一些非常極端情況(比如系統(tǒng)內(nèi)存嚴重緊缺,導(dǎo)致進程的某些需要使用的頁面被換出,并且在頁面需要換入時又無法分配到內(nèi)存……),否則這個進程不會睡眠。所以CPU的可執(zhí)行隊列總是不為空(至少有這么個進程存在),CPU也就不會“空閑”。

很多操作系統(tǒng)教科書將正在CPU上執(zhí)行的進程定義為RUNNING狀態(tài)、而將可執(zhí)行但是尚未被調(diào)度執(zhí)行的進程定義為READY狀態(tài),這兩種狀態(tài)在linux下統(tǒng)一為 TASK_RUNNING狀態(tài)。

S (TASK_INTERRUPTIBLE),可中斷的睡眠狀態(tài)。

處于這個狀態(tài)的進程因為等待某某事件的發(fā)生(比如等待socket連接、等待信號量),而被掛起。這些進程的task_struct結(jié)構(gòu)被放入對應(yīng)事件的等待隊列中。當(dāng)這些事件發(fā)生時(由外部中斷觸發(fā)、或由其他進程觸發(fā)),對應(yīng)的等待隊列中的一個或多個進程將被喚醒。

通過ps命令我們會看到,一般情況下,進程列表中的絕大多數(shù)進程都處于TASK_INTERRUPTIBLE狀態(tài)(除非機器的負載很高)。畢竟CPU就這么一兩個,進程動輒幾十上百個,如果不是絕大多數(shù)進程都在睡眠,CPU又怎么響應(yīng)得過來。

D (TASK_UNINTERRUPTIBLE),不可中斷的睡眠狀態(tài)。

與TASK_INTERRUPTIBLE狀態(tài)類似,進程處于睡眠狀態(tài),但是此刻進程是不可中斷的。不可中斷,指的并不是CPU不響應(yīng)外部硬件的中斷,而是指進程不響應(yīng)異步信號。

絕大多數(shù)情況下,進程處在睡眠狀態(tài)時,總是應(yīng)該能夠響應(yīng)異步信號的。否則你將驚奇的發(fā)現(xiàn),kill -9竟然殺不死一個正在睡眠的進程了!于是我們也很好理解,為什么ps命令看到的進程幾乎不會出現(xiàn)TASK_UNINTERRUPTIBLE狀態(tài),而總是TASK_INTERRUPTIBLE狀態(tài)。

而TASK_UNINTERRUPTIBLE狀態(tài)存在的意義就在于,內(nèi)核的某些處理流程是不能被打斷的。如果響應(yīng)異步信號,程序的執(zhí)行流程中就會被插入一段用于處理異步信號的流程(這個插入的流程可能只存在于內(nèi)核態(tài),也可能延伸到用戶態(tài)),于是原有的流程就被中斷了(參見《linux異步信號handle淺析》)。

在進程對某些硬件進行操作時(比如進程調(diào)用read系統(tǒng)調(diào)用對某個設(shè)備文件進行讀操作,而read系統(tǒng)調(diào)用最終執(zhí)行到對應(yīng)設(shè)備驅(qū)動的代碼,并與對應(yīng)的物理設(shè)備進行交互),可能需要使用TASK_UNINTERRUPTIBLE狀態(tài)對進程進行保護,以避免進程與設(shè)備交互的過程被打斷,造成設(shè)備陷入不可控的狀態(tài)。(比如read系統(tǒng)調(diào)用觸發(fā)了一次磁盤到用戶空間的內(nèi)存的DMA,如果DMA進行過程中,進程由于響應(yīng)信號而退出了,那么DMA正在訪問的內(nèi)存可能就要被釋放了。)這種情況下的TASK_UNINTERRUPTIBLE狀態(tài)總是非常短暫的,通過ps命令基本上不可能捕捉到。

linux系統(tǒng)中也存在容易捕捉的TASK_UNINTERRUPTIBLE狀態(tài)。執(zhí)行vfork系統(tǒng)調(diào)用后,父進程將進入TASK_UNINTERRUPTIBLE狀態(tài),直到子進程調(diào)用exit或exec。

通過下面的代碼就能得到處于TASK_UNINTERRUPTIBLE狀態(tài)的進程:

#include <unistd.h>

void main() {

if (!vfork()) sleep(100);

}

編譯運行,然后ps一下:

kouu@kouu-one:~/test$ ps -ax | grep a\.out

4371 pts/0    D+     0:00 ./a.out

4372 pts/0    S+     0:00 ./a.out

4374 pts/1    S+     0:00 grep a.out

然后我們可以試驗一下TASK_UNINTERRUPTIBLE狀態(tài)的威力。不管kill還是kill -9,這個TASK_UNINTERRUPTIBLE狀態(tài)的父進程依然屹立不倒。

T (TASK_STOPPED or TASK_TRACED),暫停狀態(tài)或跟蹤狀態(tài)。

向進程發(fā)送一個SIGSTOP信號,它就會因響應(yīng)該信號而進入TASK_STOPPED狀態(tài)(除非該進程本身處于TASK_UNINTERRUPTIBLE狀態(tài)而不響應(yīng)信號)。(SIGSTOP與SIGKILL信號一樣,是非常強制的。不允許用戶進程通過signal系列的系統(tǒng)調(diào)用重新設(shè)置對應(yīng)的信號處理函數(shù)。)

向進程發(fā)送一個SIGCONT信號,可以讓其從TASK_STOPPED狀態(tài)恢復(fù)到TASK_RUNNING狀態(tài)。

當(dāng)進程正在被跟蹤時,它處于TASK_TRACED這個特殊的狀態(tài)。“正在被跟蹤”指的是進程暫停下來,等待跟蹤它的進程對它進行操作。比如在gdb中對被跟蹤的進程下一個斷點,進程在斷點處停下來的時候就處于TASK_TRACED狀態(tài)。而在其他時候,被跟蹤的進程還是處于前面提到的那些狀態(tài)。

對于進程本身來說,TASK_STOPPED和TASK_TRACED狀態(tài)很類似,都是表示進程暫停下來。。

而TASK_TRACED狀態(tài)相當(dāng)于在TASK_STOPPED之上多了一層保護,處于TASK_TRACED狀態(tài)的進程不能響應(yīng)SIGCONT信號而被喚醒。只能等到調(diào)試進程通過ptrace系統(tǒng)調(diào)用執(zhí)行PTRACE_CONT、PTRACE_DETACH等操作(通過ptrace系統(tǒng)調(diào)用的參數(shù)指定操作),或調(diào)試進程退出,被調(diào)試的進程才能恢復(fù)TASK_RUNNING狀態(tài)。

Z (TASK_DEAD - EXIT_ZOMBIE),退出狀態(tài),進程成為僵尸進程。

進程在退出的過程中,處于TASK_DEAD狀態(tài)。

在這個退出過程中,進程占有的所有資源將被回收,除了task_struct結(jié)構(gòu)(以及少數(shù)資源)以外。于是進程就只剩下task_struct這么個空殼,故稱為僵尸。

之所以保留task_struct,是因為task_struct里面保存了進程的退出碼、以及一些統(tǒng)計信息。而其父進程很可能會關(guān)心這些信息。比如在shell中,$?變量就保存了最后一個退出的前臺進程的退出碼,而這個退出碼往往被作為if語句的判斷條件。

當(dāng)然,內(nèi)核也可以將這些信息保存在別的地方,而將task_struct結(jié)構(gòu)釋放掉,以節(jié)省一些空間。但是使用task_struct結(jié)構(gòu)更為方便,因為在內(nèi)核中已經(jīng)建立了從pid到task_struct查找關(guān)系,還有進程間的父子關(guān)系。釋放掉task_struct,則需要建立一些新的數(shù)據(jù)結(jié)構(gòu),以便讓父進程找到它的子進程的退出信息。

父進程可以通過wait系列的系統(tǒng)調(diào)用(如wait4、waitid)來等待某個或某些子進程的退出,并獲取它的退出信息。然后wait系列的系統(tǒng)調(diào)用會順便將子進程的尸體(task_struct)也釋放掉。

子進程在退出的過程中,內(nèi)核會給其父進程發(fā)送一個信號,通知父進程來“收尸”。這個信號默認是SIGCHLD,但是在通過clone系統(tǒng)調(diào)用創(chuàng)建子進程時,可以設(shè)置這個信號。

通過下面的代碼能夠制造一個EXIT_ZOMBIE狀態(tài)的進程:

#include <unistd.h>

void main() {

if (fork())

while(1) sleep(100);

}

編譯運行,然后ps一下:

kouu@kouu-one:~/test$ ps -ax | grep a\.out

10410 pts/0    S+     0:00 ./a.out

10411 pts/0    Z+     0:00 [a.out] <defunct>

10413 pts/1    S+     0:00 grep a.out

只要父進程不退出,這個僵尸狀態(tài)的子進程就一直存在。那么如果父進程退出了呢,誰又來給子進程“收尸”?

當(dāng)進程退出的時候,會將它的所有子進程都托管給別的進程(使之成為別的進程的子進程)。托管給誰呢?可能是退出進程所在進程組的下一個進程(如果存在的話),或者是1號進程。所以每個進程、每時每刻都有父進程存在。除非它是1號進程。

1號進程,pid為1的進程,又稱init進程。

linux系統(tǒng)啟動后,第一個被創(chuàng)建的用戶態(tài)進程就是init進程。它有兩項使命:

1、執(zhí)行系統(tǒng)初始化腳本,創(chuàng)建一系列的進程(它們都是init進程的子孫);

2、在一個死循環(huán)中等待其子進程的退出事件,并調(diào)用waitid系統(tǒng)調(diào)用來完成“收尸”工作;

init進程不會被暫停、也不會被殺死(這是由內(nèi)核來保證的)。它在等待子進程退出的過程中處于TASK_INTERRUPTIBLE狀態(tài),“收尸”過程中則處于TASK_RUNNING狀態(tài)。

 X(TASK_DEAD - EXIT_DEAD),退出狀態(tài),進程即將被銷毀。

而進程在退出過程中也可能不會保留它的task_struct。比如這個進程是多線程程序中被detach過的進程。或者父進程通過設(shè)置SIGCHLD信號的handler為SIG_IGN,顯式的忽略了SIGCHLD信號。(這是posix的規(guī)定,盡管子進程的退出信號可以被設(shè)置為SIGCHLD以外的其他信號。)

此時,進程將被置于EXIT_DEAD退出狀態(tài),這意味著接下來的代碼立即就會將該進程徹底釋放。所以EXIT_DEAD狀態(tài)是非常短暫的,幾乎不可能通過ps命令捕捉到。

進程的初始狀態(tài)

進程是通過fork系列的系統(tǒng)調(diào)用(fork、clone、vfork)來創(chuàng)建的,內(nèi)核(或內(nèi)核模塊)也可以通過kernel_thread函數(shù)創(chuàng)建內(nèi)核進程。這些創(chuàng)建子進程的函數(shù)本質(zhì)上都完成了相同的功能——將調(diào)用進程復(fù)制一份,得到子進程。(可以通過選項參數(shù)來決定各種資源是共享、還是私有。)

那么既然調(diào)用進程處于TASK_RUNNING狀態(tài)(否則,它若不是正在運行,又怎么進行調(diào)用?),則子進程默認也處于TASK_RUNNING狀態(tài)。

另外,在系統(tǒng)調(diào)用調(diào)用clone和內(nèi)核函數(shù)kernel_thread也接受CLONE_STOPPED選項,從而將子進程的初始狀態(tài)置為 TASK_STOPPED。

進程狀態(tài)變遷

進程自創(chuàng)建以后,狀態(tài)可能發(fā)生一系列的變化,直到進程退出。而盡管進程狀態(tài)有好幾種,但是進程狀態(tài)的變遷卻只有兩個方向——從TASK_RUNNING狀態(tài)變?yōu)榉荰ASK_RUNNING狀態(tài)、或者從非TASK_RUNNING狀態(tài)變?yōu)門ASK_RUNNING狀態(tài)。

也就是說,如果給一個TASK_INTERRUPTIBLE狀態(tài)的進程發(fā)送SIGKILL信號,這個進程將先被喚醒(進入TASK_RUNNING狀態(tài)),然后再響應(yīng)SIGKILL信號而退出(變?yōu)門ASK_DEAD狀態(tài))。并不會從TASK_INTERRUPTIBLE狀態(tài)直接退出。

進程從非TASK_RUNNING狀態(tài)變?yōu)門ASK_RUNNING狀態(tài),是由別的進程(也可能是中斷處理程序)執(zhí)行喚醒操作來實現(xiàn)的。執(zhí)行喚醒的進程設(shè)置被喚醒進程的狀態(tài)為TASK_RUNNING,然后將其task_struct結(jié)構(gòu)加入到某個CPU的可執(zhí)行隊列中。于是被喚醒的進程將有機會被調(diào)度執(zhí)行。

而進程從TASK_RUNNING狀態(tài)變?yōu)榉荰ASK_RUNNING狀態(tài),則有兩種途徑:

1、響應(yīng)信號而進入TASK_STOPED狀態(tài)、或TASK_DEAD狀態(tài);

2、執(zhí)行系統(tǒng)調(diào)用主動進入TASK_INTERRUPTIBLE狀態(tài)(如nanosleep系統(tǒng)調(diào)用)、或TASK_DEAD狀態(tài)(如exit系統(tǒng)調(diào)用);或由于執(zhí)行系統(tǒng)調(diào)用需要的資源得不到滿足,而進入TASK_INTERRUPTIBLE狀態(tài)或TASK_UNINTERRUPTIBLE狀態(tài)(如select系統(tǒng)調(diào)用)。

顯然,這兩種情況都只能發(fā)生在進程正在CPU上執(zhí)行的情況下。


關(guān)鍵字:Centos、進程狀態(tài)、CPU
分享到:

頂部 】 【 關(guān)閉
版權(quán)所有:佛山思海電腦網(wǎng)絡(luò)有限公司 ©1998-2024 All Rights Reserved.
聯(lián)系電話:(0757)22630313、22633833
中華人民共和國增值電信業(yè)務(wù)經(jīng)營許可證: 粵B1.B2-20030321 備案號:粵B2-20030321-1
網(wǎng)站公安備案編號:44060602000007 交互式欄目專項備案編號:200303DD003  
察察 工商 網(wǎng)安 舉報有獎  警警  手機打開網(wǎng)站