在 Linux 系統編程中,進程(Process) 是操作系統進行資源分配和調度的基本單位。理解進程的概念是掌握系統編程、多任務處理、并發編程的基礎。
目錄
一、什么是進程?
定義:
二、進程的生命周期
示例:查看當前系統中的進程
三、進程的狀態(STAT)
四、進程的父子關系與進程樹
示例:查看進程樹
關鍵概念:
五、進程標識符(PID 和 PPID)
示例:查看當前 shell 的 PID 和 PPID
六、前臺進程與后臺進程
示例:將進程放入后臺運行
七、進程的優先級(Nice 值)
查看 nice 值:
設置 nice 值啟動進程:
修改已有進程的 nice 值:
八、進程相關的系統調用(C語言接口)
九、第一個 C 程序:演示 fork() 創建進程
示例代碼:process_example.c
編譯并運行:
十、總結知識點圖解(知識樹狀圖)
十一、課后練習建議
一、什么是進程?
定義:
進程是一個程序的執行實例,包括:
- 程序代碼(Text Segment)
- 當前活動(如寄存器的狀態、程序計數器等)
- 數據段(Data Segment)
- 堆棧(Stack)
- 打開的文件、信號處理函數等資源
簡單來說:一個正在運行的程序就是一個進程。
二、進程的生命周期
一個進程從創建到終止,會經歷以下幾個階段:
+-------------------+
| 創建進程 | fork()
+-------------------+|v
+-------------------+
| 運行/就緒狀態 |
+-------------------+|v
+-------------------+
| 阻塞(等待I/O等) |
+-------------------+|v
+-------------------+
| 終止或退出 | exit(), _exit()
+-------------------+
示例:查看當前系統中的進程
ps aux
輸出示例(簡化):
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.2 168944 9348 ? Ss 09:00 0:01 /sbin/init
user1 1234 0.1 0.5 500000 20000 ? Sl 09:10 0:02 /usr/bin/vim
各列含義簡要說明:
列名 | 含義 |
---|---|
USER | 進程所有者 |
PID | 進程 ID |
%CPU | 占用 CPU 百分比 |
%MEM | 占用內存百分比 |
VSZ | 虛擬內存使用量(KB) |
RSS | 實際物理內存使用量(KB) |
TTY | 控制終端 |
STAT | 進程狀態 |
START | 進程啟動時間 |
TIME | 占用 CPU 時間總和 |
COMMAND | 啟動命令 |
三、進程的狀態(STAT)
Linux 中進程常見的狀態有以下幾種:
狀態字符 | 含義 |
---|---|
R (Running) | 正在運行或準備運行 |
S (Sleeping) | 可中斷的睡眠狀態(等待某事件) |
D (Disk Sleep) | 不可中斷的睡眠(通常在 I/O) |
Z (Zombie) | 僵尸進程(已結束但未被回收) |
T (Stopped) | 被停止(如收到 SIGSTOP) |
X (Dead) | 已死亡(不會出現在 ps 中) |
四、進程的父子關系與進程樹
每個進程都有一個父進程(除了 init/systemd),通過 fork()
創建子進程。
示例:查看進程樹
pstree
輸出示例:
systemd─┬─NetworkManager───2*[{NetworkManager}]├─login───bash└─sshd───bash───vim
關鍵概念:
- 父進程(Parent Process):創建其他進程的進程。
- 子進程(Child Process):由父進程創建的進程。
- 僵尸進程(Zombie Process):子進程結束后,父進程沒有調用?
wait()
?或?waitpid()
?獲取其退出狀態,該子進程變成僵尸進程。 - 孤兒進程(Orphan Process):父進程先于子進程結束,子進程成為孤兒進程,由?
init
(PID=1)接管。
五、進程標識符(PID 和 PPID)
- PID(Process ID):進程的唯一標識號。
- PPID(Parent Process ID):父進程的 PID。
示例:查看當前 shell 的 PID 和 PPID
echo "Current PID: $$"
echo "Parent PID: $PPID"
輸出示例:
Current PID: 12345
Parent PID: 11111
你也可以使用 ps
查看詳細信息:
ps -p 12345 -o pid,ppid,comm
六、前臺進程與后臺進程
- 前臺進程:占用終端,用戶可以直接交互。
- 后臺進程:不占用終端,通常用于長時間運行的任務。
示例:將進程放入后臺運行
sleep 100 & # 在后臺運行
查看后臺進程:
jobs
七、進程的優先級(Nice 值)
Linux 使用 nice 值 來控制進程的優先級,默認值為 0,范圍為 -20(最高優先級)到 19(最低優先級)。
查看 nice 值:
ps -l
設置 nice 值啟動進程:
nice -n 10 sleep 100 &
修改已有進程的 nice 值:
renice 5 -p 12345
八、進程相關的系統調用(C語言接口)
這些是 Linux 編程中最常用的系統調用:
系統調用 | 功能描述 |
---|---|
fork() | 創建子進程 |
exec() ?系列 | 替換當前進程為新程序 |
wait() | 等待子進程結束 |
exit() | 終止當前進程 |
getpid() | 獲取當前進程的 PID |
getppid() | 獲取父進程的 PID |
九、第一個 C 程序:演示 fork() 創建進程
示例代碼:process_example.c
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>int main() {pid_t pid;printf("Before fork: This is the parent process (PID: %d)\n", getpid());pid = fork(); // 創建子進程if (pid < 0) {fprintf(stderr, "Fork failed\n");return 1;} else if (pid == 0) {// 子進程printf("This is the child process (PID: %d), Parent PID: %d\n", getpid(), getppid());} else {// 父進程printf("This is the parent process again (PID: %d), Child PID: %d\n", getpid(), pid);}return 0;
}
編譯并運行:
gcc process_example.c -o process_example
./process_example
輸出示例(順序可能不同):
Before fork: This is the parent process (PID: 12345)
This is the parent process again (PID: 12345), Child PID: 12346
This is the child process (PID: 12346), Parent PID: 1
注意:由于父進程和子進程是并發執行的,所以輸出順序可能不確定。
十、總結知識點圖解(知識樹狀圖)
進程的概念
│
├── 什么是進程?
│ ├── 程序的執行實例
│ └── 包含代碼、數據、堆棧、資源等
│
├── 進程生命周期
│ ├── 創建 → 運行 → 阻塞 → 終止
│ └── fork(), exec(), exit()
│
├── 進程狀態(STAT)
│ ├── R/S/D/Z/T/X
│
├── 進程關系與進程樹
│ ├── 父進程與子進程
│ ├── 僵尸進程 vs 孤兒進程
│ └── pstree 命令查看樹結構
│
├── 進程標識符
│ ├── PID(當前進程ID)
│ └── PPID(父進程ID)
│
├── 前臺進程 vs 后臺進程
│ ├── jobs, &, fg, bg
│
├── 進程優先級(nice)
│ ├── nice, renice 命令
│
└── 進程相關系統調用(C語言)├── fork()├── exec()├── wait()├── exit()├── getpid()└── getppid()
十一、課后練習建議
- 使用?
ps
?命令查找當前運行的所有?bash
?進程。 - 寫一個 Shell 腳本,在后臺運行多個?
sleep
?命令,并使用?jobs
?查看它們的狀態。 - 編寫一個 C 程序,使用?
fork()
?創建兩個子進程,分別打印不同的信息。 - 嘗試使用?
nice
?和?renice
?修改某個進程的優先級。