Linux进程状态、孤儿进程、僵尸进程、wait
进程状态


进程命令:
ps aux
top
kill
进程号和相关函数
pid_t
父子进程共享
共享原则: 修改前保持只读共享,修改后各自维护独立数据副本
- 初始状态: fork后父子进程共享同一地址空间,内核不立即复制整个地址空间。
- 内存映射: 通过内存映射机制,父子进程的虚拟地址指向相同的物理内存区域。
- 示例说明: 如变量
num=10num=10num=10
,初始时父子进程通过相同虚拟地址访问同一物理内存。
- 触发条件: 当任一进程执行写操作时(如修改
num=10num=10num=10
为num=11num=11num=11
),内核才进行实际拷贝。 - 拷贝过程:
- 父进程修改时:复制新内存区域存放
num=11num=11num=11
,子进程仍指向原num=10num=10num=10
- 子进程修改时:同理复制新区域存放修改值(如
num=12num=12num=12
)
- 父进程修改时:复制新内存区域存放
|
知识点 |
核心内容 |
考试重点/易混淆点 |
|
fork函数返回值 |
父进程返回子进程PID(>0),子进程返回0 |
区分父子进程的唯一依据是fork返回值 |
|
PCB内核区差异 |
父子进程的PID、PPID、信号集不同 |
内核区数据独立,用户区数据初始共享 |
|
写时拷贝机制 |
读时共享数据,写时独立拷贝 |
修改变量后父子进程互不影响,不能用于进程间通信 |
|
代码段执行逻辑 |
子进程从fork处开始执行,不重复执行上方代码 |
父子进程代码段相同,通过返回值判断执行分支 |
|
GDB多进程调试 |
默认跟踪父进程,子进程自动运行 |
通过set follow-fork-mode设置跟踪父/子进程 |
|
detach-on-fork参数 |
on:其他进程脱离GDB控制;off:其他进程挂起在fork处 |
off模式下可通过inferior命令切换调试进程 |
|
inferior命令 |
查看所有进程列表,切换调试目标进程 |
使用inferior 编号切换,detach inferior 编号分离进程 |
|
对比项 |
父进程 |
子进程 |
|
fork返回值 |
子进程PID(>0) |
0 |
|
GDB默认跟踪 |
是(parent模式) |
否(需设置child模式) |
|
数据独立性 |
写时拷贝后独立 |
写时拷贝后独立 |
|
调试切换方式 |
inferior 1 |
inferior 2 |
|
脱离GDB控制 |
detach inferior 1 |
detach inferior 2 |
|
命令 |
功能 |
使用场景 |
|
set follow-fork-mode parent/child |
设置GDB跟踪父/子进程 |
调试前配置 |
|
set detach-on-fork on/off |
设置其他进程是否脱离GDB |
多进程调试控制 |
|
info inferiors |
查看所有进程列表 |
查看当前调试进程 |
|
inferior 编号 |
切换到指定进程 |
切换调试目标 |
|
detach inferior 编号 |
使指定进程脱离GDB |
释放进程控制 |
|
show follow-fork-mode |
查看当前跟踪模式 |
确认当前配置 |
exec函数
- 替换机制: 将当前进程的用户区数据(代码段、数据段、堆栈等)完全替换为新程序的内容,仅保留进程ID等内核区信息。
- 形象比喻: 类似"金蝉脱壳",保持原进程外壳(进程ID等),但注入新程序"灵魂"(代码和数据)。
- 执行起点: 新程序从main函数开始执行,完全替代原程序的执行流程。
将当前进程的用户区替换成要执行的文件的用户段,并存替换的main开始执行(内核保留)
exit
exit比_exit多了两个步骤。

带来效果:exit输出world _exit不输出
原因:对于这个代码
第二个printf因为没有加\n所以会加载到缓冲区,exit会刷新缓冲区,能输出出来
带有 \n)或程序正常 return 0 退出,都会触发刷盘,把缓冲区里的 hi 打印到屏幕上。

孤儿进程
产生条件:父进程先于子进程终止
- 变化现象:
- 父进程终止后子进程ppid变为1
- 初始时子进程ppid为父进程pid
- 原因说明:
- 父进程终止后内核将孤儿进程分配给init进程(pid=1)
- init进程成为新的父进程负责资源回收
- 回收机制:
- 避免僵尸进程产生
- 由init进程(pid=1)负责回收孤儿进程资源
- 无害性:
- 不会造成资源泄漏
- 系统自动处理无需人工干预
僵尸进程
-
- 产生原因:
- 进程终止时会释放用户区数据(栈、堆等),但内核区的PCB(进程控制块)需要父进程调用wait()或waitpid()来释放
- 当父进程未及时回收子进程资源时,子进程的PCB残留内核中形成僵尸进程
- 特性:
- 无法被kill -9命令终止
- 进程状态显示为Z(Zombie)和<defunct>标记
- 危害:
- 占用系统进程号资源(PID有限)
- 大量僵尸进程会导致系统无法创建新进程
- 解决方法:
- 父进程必须调用wait()或waitpid()回收子进程资源
- 杀死父进程(临时方案),此时僵尸进程会被init进程(PID=1)接管并回收
- 产生原因:
wait函数
-
- 僵尸进程现象:
- 子进程结束后父进程未调用wait回收,子进程会变成僵尸进程(状态为Z+)
- 使用ps aux命令可以查看僵尸进程
- wait函数调用:
- 父进程中调用wait(NULL)会阻塞等待子进程结束
- 当有子进程结束时(可用kill -9),wait会返回该子进程的pid
- 当所有子进程都已结束时,wait会返回-1
- 循环回收:
- 通常将wait放在循环中,以便回收所有子进程
- 当wait返回-1时可以通过break退出循环
- 僵尸进程现象:
- 注意事项
- 一次回收一个:wait函数一次只能回收一个子进程
- 阻塞特性:默认是阻塞的,会暂停父进程执行直到有子进程结束
- 资源回收:成功调用wait后会回收子进程资源,避免僵尸进程
- 状态获取:可以通过wstatus参数获取子进程退出状态(演示中使用NULL表示不关心退出状态)
waitpid
- 功能相似性:两者都用于回收子进程资源
- 主要区别:
- wait只能回收任意子进程,waitpid可指定特定子进程
- waitpid提供更多控制选项(如WNOHANG非阻塞模式)
- waitpid可以回收指定进程组的子进程
更多推荐

所有评论(0)