進程是 Linux 作業系統中最重要的基本概念之一,這一節我們將了解學習 Linux 進程的一些基礎知識。
進程是執行在 Linux 中的程式的一個範例。這是一個你之前就可能已經聽說過的基本定義。
當你在 Linux 系統中執行一個程式時,系統會為這個程式建立特定的環境。這個環境包含系統執行這個程式所需的任何東西。
每當你在 Linux 中執行一個命令,它都會建立,或啟動一個新的進程。比如,當你嘗試執行命令“ls -l”來列出目錄的內容時,你就啟動了一個進程。如果有兩個終端視窗顯示在螢幕上,那麼你可能執行了兩次同樣的終端程式,這時會有兩個終端進程。
每個終端窗門可能都執行了一個 Shell,每個執行的 Shell 都分別是一個進程。當你從 Shell 呼叫一個命令時,對應的程式就會在一個新進程中執行,當這個程式的進程執行完成後,Shell 的進程將恢復執行。
作業系統通過被稱為 PID 或進程 ID 的數位編碼來追蹤進程。系統中的每一個進程都有一個唯一的 PID。
現在我們通過一個範例來了解 Linux 中的進程。我們在 Shell 命令列下執行如下命令:
[c.biancheng.net]$ sleep 10 &
[1] 3324
因為程式會等待 10 秒,所以我們快速地在當前 Shell 上查詢任何進程名為 sleep 的進程:
[c.biancheng.net]$ ps -ef | grep sleep
mozhiyan 3324 5712 cons1 17:11:46 /usr/bin/sleep
我們看到進程名為 /usr/bin/sleep 的進程正執行在系統中(其 PID 與我們在上一命令中得到的 PID 相同)。
現在,我們嘗試並行地從 3 個不同的終端視窗執行上述的 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 程式的每一個範例都建立了一個單獨的進程。
每個 Linux 進程還有另一個 ID 號碼,即父進程的 ID(ppid)。系統中的每一個使用者進程都有一個父進程。
命令“ps -f”就會列出進程的 PID 和 PPID。此命令的輸出類似如下所示:
[c.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 命令列提示符下執行的命令都把當前 Shell 的進程作為父進程。例如,你在 Shell 命令列提示符下輸入 ls 命令,Shell 將執行 ls 命令,此時 Linux 核心會複製 Shell 的記憶體頁,然後執行 ls 命令。
在 Unix 中,每一個進程是使用 fork 和 exec 方法建立的。然而,這種方法會導致系統資源的損耗。
在 Linux 中,fork 方法是使用寫時拷貝記憶體頁實現的,所以它導致的僅是時間和複製父進程的記憶體頁表所需的記憶體的損失,並且會為子進程建立一個唯一的任務結構。
寫時拷貝模式在建立新進程時避免了建立不必要的結構拷貝。例如,使用者在 Shell 命令列提示符下輸出 ls 命令,Linux 核心將會建立一個 Shell 的子進程,即 Shell 的進程是父進程,而 ls 命令的進程是子進程,ls 命令的進程會指向與此 Shell 相同的記憶體頁,然後子進程使用寫時拷貝技術執行 ls 命令。
前台進程和後台進程
當你啟動一個進程時(執行一個命令),可以如下兩種方式執行該進程:
預設情況下,你啟動的每一個進程都是執行在前台的。它從鍵盤獲取輸入並行送它的輸出到螢幕。
當一個進程執行在前台時,我們不能在同一命令列提示符下執行任何其他命令(啟動任何其他進程),因為在程式結束它的進程之前命令列提示符不可用。
啟動一個後台進程最簡羊的方法是新增一個控制操作符“&”到命令的結尾。例如,如下命令將啟動一個後台進程:
[c.biancheng.net]$ sleep 10 &
[1] 5720
現在 sleep 命令被放在後台執行。當 Bash 在後台啟動一個作業時,它會列印一行內容顯示作業編號([1])和進程號(PID-5720)。當作業完成時,作業會傳送類似如下的資訊到終端程式,來顯示此作業已完成,其內容類似如下所示:
[1]+ Done sleep 10
將進程放在後台執行的好處是:你可以繼續執行其他命令,而不需要等待此進程執行完成再執行其他命令。
進程的狀態
每個 Linux 進程都有它自己的生命週期,比如,建立、執行、結束和清除。每個進程也都有各自的狀態,顯示進程中當前正發生什麼。
進程可以有如下幾種狀態:
-
D(不可中斷休眠狀態)——進程正在休眠並且不能恢復,直到一個事件發生為止。
-
R(執行狀態)——進程正在執行。
-
S(休眠狀態)——進程沒有在執行,而在等待一個事件或是信號。
-
T(停止狀態)——進程被信號停止,比如,信號 SIGINT 或 SIGSTOP。
-
Z(僵死狀態)——標記為 <defunct> 的進程是僵死的進程,它們之所以殘留是因為它們的父進程適當地銷毀它們。如果父進程退出,這些進程將被 init 進程銷燬。
若要檢視指定進程的狀態,可以使用如下命令:
ps -C processName -o pid=,cmd,stat
例如:
[c.biancheng.net]$ ps -C sleep -o pid=,cmd,stat
CMD STAT
9434 sleep 20 S