進(jìn)程是 Linux 操作系統(tǒng)中最重要的基本概念之一,這一節(jié)我們將了解學(xué)習(xí) Linux 進(jìn)程的一些基礎(chǔ)知識。
進(jìn)程是運(yùn)行在 Linux 中的程序的一個實(shí)例。這是一個你之前就可能已經(jīng)聽說過的基本定義。
當(dāng)你在 Linux 系統(tǒng)中執(zhí)行一個程序時,系統(tǒng)會為這個程序創(chuàng)建特定的環(huán)境。這個環(huán)境包含系統(tǒng)運(yùn)行這個程序所需的任何東西。
每當(dāng)你在 Linux 中執(zhí)行一個命令,它都會創(chuàng)建,或啟動一個新的進(jìn)程。比如,當(dāng)你嘗試運(yùn)行命令“l(fā)s -l”來列出目錄的內(nèi)容時,你就啟動了一個進(jìn)程。如果有兩個終端窗口顯示在屏幕上,那么你可能運(yùn)行了兩次同樣的終端程序,這時會有兩個終端進(jìn)程。
每個終端窗門可能都運(yùn)行了一個 Shell,每個運(yùn)行的 Shell 都分別是一個進(jìn)程。當(dāng)你從 Shell 調(diào)用一個命令時,對應(yīng)的程序就會在一個新進(jìn)程中執(zhí)行,當(dāng)這個程序的進(jìn)程執(zhí)行完成后,Shell 的進(jìn)程將恢復(fù)運(yùn)行。
操作系統(tǒng)通過被稱為 PID 或進(jìn)程 ID 的數(shù)字編碼來追蹤進(jìn)程。系統(tǒng)中的每一個進(jìn)程都有一個唯一的 PID。
現(xiàn)在我們通過一個實(shí)例來了解 Linux 中的進(jìn)程。我們在 Shell 命令行下執(zhí)行如下命令:
[c.biancheng.net]$ sleep 10 &
?。?] 3324
因?yàn)槌绦驎却?10 秒,所以我們快速地在當(dāng)前 Shell 上查找任何進(jìn)程名為 sleep 的進(jìn)程:
?。踓.biancheng.net]$ ps -ef | grep sleep
mozhiyan 3324 5712 cons1 17:11:46 /usr/bin/sleep
我們看到進(jìn)程名為 /usr/bin/sleep 的進(jìn)程正運(yùn)行在系統(tǒng)中(其 PID 與我們在上一命令中得到的 PID 相同)。
現(xiàn)在,我們嘗試并行地從 3 個不同的終端窗口運(yùn)行上述的 sleep 命令,上述命令的輸出將類似如下所示:
[c.biancheng.net]$ ps -ef | grep sleep
mozhiyan 896 5712 cons1 17:16:51 /usr/bin/sleep
mozhiyan 5924 5712 cons1 17:16:52 /usr/bin/sleep
mozhiyan 2424 5712 cons1 17:16:50 /usr/bin/sleep
我們看到 sleep 程序的每一個實(shí)例都創(chuàng)建了一個單獨(dú)的進(jìn)程。
每個 Linux 進(jìn)程還有另一個 ID 號碼,即父進(jìn)程的 ID(ppid)。系統(tǒng)中的每一個用戶進(jìn)程都有一個父進(jìn)程。
命令“ps -f”就會列出進(jìn)程的 PID 和 PPID。此命令的輸出類似如下所示:
?。踓.biancheng.net]$ ps -f
UID PID PPID TTY STIME COMMAND
mozhiyan 4124 228 cons0 21:37:09 /usr/bin/ps
mozhiyan 228 1 cons0 21:32:23 /usr/bin/bash
你在 Shell 命令行提示符下運(yùn)行的命令都把當(dāng)前 Shell 的進(jìn)程作為父進(jìn)程。例如,你在 Shell 命令行提示符下輸入 ls 命令,Shell 將執(zhí)行 ls 命令,此時 Linux 內(nèi)核會復(fù)制 Shell 的內(nèi)存頁,然后執(zhí)行 ls 命令。
在 Unix 中,每一個進(jìn)程是使用 fork 和 exec 方法創(chuàng)建的。然而,這種方法會導(dǎo)致系統(tǒng)資源的損耗。
在 Linux 中,fork 方法是使用寫時拷貝內(nèi)存頁實(shí)現(xiàn)的,所以它導(dǎo)致的僅是時間和復(fù)制父進(jìn)程的內(nèi)存頁表所需的內(nèi)存的損失,并且會為子進(jìn)程創(chuàng)建一個唯一的任務(wù)結(jié)構(gòu)。
寫時拷貝模式在創(chuàng)建新進(jìn)程時避免了創(chuàng)建不必要的結(jié)構(gòu)拷貝。例如,用戶在 Shell 命令行提示符下輸出 ls 命令,Linux 內(nèi)核將會創(chuàng)建一個 Shell 的子進(jìn)程,即 Shell 的進(jìn)程是父進(jìn)程,而 ls 命令的進(jìn)程是子進(jìn)程,ls 命令的進(jìn)程會指向與此 Shell 相同的內(nèi)存頁,然后子進(jìn)程使用寫時拷貝技術(shù)執(zhí)行 ls 命令。
前臺進(jìn)程和后臺進(jìn)程
當(dāng)你啟動一個進(jìn)程時(運(yùn)行一個命令),可以如下兩種方式運(yùn)行該進(jìn)程:
前臺進(jìn)程
后臺進(jìn)程
默認(rèn)情況下,你啟動的每一個進(jìn)程都是運(yùn)行在前臺的。它從鍵盤獲取輸入并發(fā)送它的輸出到屏幕。
當(dāng)一個進(jìn)程運(yùn)行在前臺時,我們不能在同一命令行提示符下運(yùn)行任何其他命令(啟動任何其他進(jìn)程),因?yàn)樵诔绦蚪Y(jié)束它的進(jìn)程之前命令行提示符不可用。
啟動一個后臺進(jìn)程最簡羊的方法是添加一個控制操作符“&”到命令的結(jié)尾。例如,如下命令將啟動一個后臺進(jìn)程:
?。踓.biancheng.net]$ sleep 10 &
[1] 5720
現(xiàn)在 sleep 命令被放在后臺運(yùn)行。當(dāng) Bash 在后臺啟動一個作業(yè)時,它會打印一行內(nèi)容顯示作業(yè)編號([1])和進(jìn)程號(PID-5720)。當(dāng)作業(yè)完成時,作業(yè)會發(fā)送類似如下的信息到終端程序,來顯示此作業(yè)已完成,其內(nèi)容類似如下所示:
?。?]+ Done sleep 10
將進(jìn)程放在后臺運(yùn)行的好處是:你可以繼續(xù)運(yùn)行其他命令,而不需要等待此進(jìn)程運(yùn)行完成再運(yùn)行其他命令。
進(jìn)程的狀態(tài)
每個 Linux 進(jìn)程都有它自己的生命周期,比如,創(chuàng)建、執(zhí)行、結(jié)束和清除。每個進(jìn)程也都有各自的狀態(tài),顯示進(jìn)程中當(dāng)前正發(fā)生什么。
進(jìn)程可以有如下幾種狀態(tài):
D(不可中斷休眠狀態(tài))——進(jìn)程正在休眠并且不能恢復(fù),直到一個事件發(fā)生為止。
R(運(yùn)行狀態(tài))——進(jìn)程正在運(yùn)行。
S(休眠狀態(tài))——進(jìn)程沒有在運(yùn)行,而在等待一個事件或是信號。
T(停止?fàn)顟B(tài))——進(jìn)程被信號停止,比如,信號 SIGINT 或 SIGSTOP。
Z(僵死狀態(tài))——標(biāo)記為 《defunct》 的進(jìn)程是僵死的進(jìn)程,它們之所以殘留是因?yàn)樗鼈兊母高M(jìn)程適當(dāng)?shù)劁N毀它們。如果父進(jìn)程退出,這些進(jìn)程將被 init 進(jìn)程銷毀。
若要查看指定進(jìn)程的狀態(tài),可以使用如下命令:
ps -C processName -o pid=,cmd,stat
例如:
?。踓.biancheng.net]$ ps -C sleep -o pid=,cmd,stat
CMD STAT
9434 sleep 20 S
電子發(fā)燒友App





























評論