10.2 进程和僵尸进程
2025/12/11大约 4 分钟
10.2 进程和僵尸进程
修改10.1的程序,增加子进程pid的打印,以及创建子进程后父进程sleep
实现:
printf("Parent Process: pid = %d, i = %d\n", pid, i);
sleep(30);效果:
程序输出:
Parent Process: pid = 2144, i = 2
Child Process: i = 5使用另一个终端查看进程状态
或 在运行程序后添加 & 参数让程序后台运行:
ming 2143 0.0 0.0 4352 676 pts/8 S+ 01:44 0:00 ./Network
ming 2144 0.0 0.0 0 0 pts/8 Z+ 01:44 0:00 [Network] <defunct>子进程的pid是2144,COMMAND中显示为 [Network] <defunct> 不再使用
虽然子进程已经返回了,但是父进程还在,操作系统不会自动销毁子进程。子进程占用的资源也不会释放。
子进程的终止方式:
main函数中执行return语句并返回值
问:这里说明的是main函数执行结束,那如果在子进程中创建进程(孙子进程)。现在有3辈人:爷、父、孙,父终止的时候孙会跟着终止吗?换句话说,这里main 返回是独指main,还是指main代表的父进程?传递参数并调用exit函数
由父进程显式要求回收子进程,获取子进程的返回状态并终止子进程,回收子进程占用的资源。
回收子进程
NAME
wait, waitpid, waitid - wait for process to change state
SYNOPSIS
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *status);
pid_t waitpid(pid_t pid, int *status, int options);| 参数 | 值 | 用途 | 说明 |
|---|---|---|---|
| pid | < -1 meaning wait for any child process whose process group ID is equal to the absolute value of pid. -1 meaning wait for any child process. 0 meaning wait for any child process whose process group ID is equal to that of the calling process. > 0 meaning wait for the child whose process ID is equal to the value of pid. | 指定监视的process的范围 | -1: 任何子进程; group ID:一组关联的进程,父子进程属于一个进程组 什么情况下需要指定group ID? |
| status | WIFEXITED(status):子进程是否正常退出(使用exit 或 从main 返回) WEXITSTATUS(status): returns the exit status of the child. WIFSIGNALED:returns true if the child process was terminated by a signal. | 存储回收进程的状态信息 | 使用宏来获取status存储的具体信息 |
| option | WNOHANG return immediately if no child has exited. WUNTRACED also return if a child has stopped (but not traced via ptrace(2)). Status for traced children which have stopped is provided even if this option is not specified. | 控制回收的方式 | WNOHANG:如果在调用wait时子进程的状态没有变化,wait会一直等待,直到有状态变化。如果wait前,子进程已经发生的变化(返回),wait会直接返回。设置该选项后,不管是否有变化,wait都直接返回。 WUNTRACED: 正常情况下,wait只返回已经终止的子进程。如果要获知停止状态的子进程,需要设置WUNTRACED。对于被traced的进程(调试时),无论是否设置WUNTRACED,都会返回。相当于默认被设置 |
wait( ) <=> waitpid(-1, &status, 0)
查看进程组
命令:
ps -e --format pid,pgid,sid,ppid,comm| 参数 | 含义 |
|---|---|
| -e | every 所有的进程 |
| --format | 自定义ps输出的内容(格式) |
| pgid | process group ID or, equivalently, the process ID of the process group leader. (alias pgrp). |
| sid | session ID or, equivalently, the process ID of the session leader. session 就当作是所在的终端 |
| ppid | parent process ID. |
输出:
PID PGID SID PPID COMMAND
...
1956 1956 1956 954 sshd
2024 1956 1956 1956 sshd
2026 2026 2026 2024 bash
2036 2036 2036 2025 sftp-server
2344 0 0 2 kworker/u2:2
2370 0 0 2 kworker/u2:1
2374 0 0 2 kworker/u2:0
2401 2401 2026 2026 Network
2402 2401 2026 2401 Network
2403 2401 2026 2402 NetworkNetwork 是由 2026bash 创建的,所以其ppid是2026,而2026bash 是一个 terminal,所以其sid就是它本身。
2401Network创建了2402,2402又创建了2403, 他们的PGID 是最先启动的2401.
测试
- 调用wait 前子进程已经返回
int main(int argc, char* argv[])
{
int i = 3;
pid_t pid;
pid = fork();
if(pid == -1)
unix_error("fork error");
else if(pid == 0) { // child process
i += 2;
printf("child process: i = %d\n", i);
return i;
} else { // parent process
sleep(1);
int status;
printf("before wait\n");
waitpid(pid, &status, 0);
printf("ifexited: %d, status: %d, ifsignaled: %d\n", WIFEXITED(status), WEXITSTATUS(status), WIFSIGNALED(status));
}
return 0;
}输出:
child process: i = 5
before wait
ifexited: 1, status: 5, ifsignaled: 0- 调用wait 时子进程还没有返回
让子进程sleep
输出:
before wait
child process: i = 5
ifexited: 1, status: 5, ifsignaled: 0等待直到子进程返回