一、孤儿进程
| 项目 | 内容 |
|---|---|
| 定义 | 父进程先于子进程终止,该子进程就成为孤儿进程 (正常的进程)不是一种进程的状态 |
| 产生原因 | 父进程意外崩溃、被强制终止(如kill -9),或父进程主动退出但未正确处理子进程 |
| 特点 | 被系统的“祖先进程(一号进程)”(Linux 中是 init 或 systemd,PID=1)收养 仍能正常运行,完成自身任务后正常终止 不会占用额外资源 |
| 影响 | 本身是系统正常处理机制的结果,无负面影响,反而避免了进程成为“无主进程” |
| 示例 | 若父进程因 bug 崩溃,子进程被 init 收养后可继续提供服务 |
二、僵尸进程
| 项目 | 内容 |
|---|---|
| 定义 | 进程已终止,但内核未释放其进程控制块(PCB),进程状态变为 Z(僵尸态) |
| 产生原因 | 父进程未调用wait()或waitpid()等系统调用来读取子进程的退出状态(如退出码、终止原因),导致内核无法回收 PCB |
| 特点 | • 已终止运行,不再执行任何代码,但 PCB 仍占用内存资源(如 PID、退出状态) • 通过 ps命令显示状态为Z或Z+(僵尸态),名称可能为<defunct> |
| 影响 | • 系统 PID 数量有限,大量僵尸进程会耗尽 PID 资源,导致新进程无法创建 • 不占用用户空间的内存数据段,但内核空间的 PCB 资源仍被占用且无法使用 |
| 处理方式 | •预防:父进程调用wait()/waitpid()主动回收子进程状态•清除: kill -9无法直接杀死僵尸进程(其已终止,无运行实体);若父进程未处理,可终止父进程(僵尸进程被 1 号进程收养,1 号进程会定期回收其 PCB) |
三、守护进程
3.1 介绍
| 项目 | 内容 |
|---|---|
| 定义 | 运行在后台的特殊进程,独立于控制终端,用于持续提供系统服务 |
| 设计目的 | 不受用户登录/注销影响,长期稳定运行(如网络服务、定时任务) |
| 特点 | •脱离终端:无控制终端,避免终端关闭导致进程终止 •后台运行:通过 ps命令查看状态通常为S(休眠),名称多以d结尾(如httpd、systemd)•父进程为1号进程:启动后会与原本父进程脱离,被1号进程收养 •环境干净:默认不继承终端信号,工作目录通常为 /,文件描述符(如stdin/stdout/stderr)被关闭或重定向到/dev/null |
3.2 守护进程创建流程
| 步骤 | 操作 | 目的 |
|---|---|---|
| 1 | 父进程fork()后退出 | 子进程成为孤儿进程,被 init/systemd(PID=1)收养,脱离原终端控制 |
| 2 | 子进程调用setsid() | 创建新会话,成为会话组长,脱离原控制终端,确保进程不再与任何终端关联 |
| 3 | 调用chdir("/") | 将工作目录改为根目录(或其它不会被删除/卸载的目录),避免占用可卸载文件系统(如挂载点)导致无法卸载 |
| 4 | 调用umask(0) | 修改文件创建掩码为 0,使守护进程创建文件时拥有完全权限(避免继承父进程的掩码限制) |
| 5 | 关闭所有继承的文件描述符 | 释放父进程继承的 stdin/stdout/stderr 及其他打开的文件描述符,节省资源并避免意外操作 |
| 6 | 使用dup()/dup2()重定向 | 将标准输入、标准输出、标准错误重定向到/dev/null或日志文件,防止守护进程意外输出导致错误 |
| 7 | 开启自己的服务 | 执行守护进程的核心功能(如网络监听、定时任务等),长期稳定运行 |
3.3 相关函数
3.3.1 setsid函数
| 项目 | 内容 |
|---|---|
| 头文件 | <sys/types.h><unistd.h> |
| 原型 | pid_t setsid(void); |
| 功能 | 创建一个新会话,并让调用进程成为该新会话的首进程,同时也成为新进程组的组长 |
| 参数 | 无 |
| 返回值 | • 成功:返回调用进程的新会话标识符(会话ID) • 失败:返回 -1,并设置errno指示错误原因 |
| 备注 | 调用进程不能是进程组组长,否则会失败;通常通过先fork()让父进程退出,子进程(非组长)再调用setsid() |
3.3.2 chdir函数
| 项目 | 内容 |
|---|---|
| 头文件 | <unistd.h> |
| 原型 | int chdir(const char *path); |
| 功能 | 将调用进程的当前工作目录修改为参数path所指定的目录 |
| 参数 | path— 新的工作目录路径(字符串) |
| 返回值 | • 成功:返回0• 失败:返回 -1,并设置errno指示错误原因 |
3.3.3 umask函数
| 项目 | 内容 |
|---|---|
| 头文件 | <sys/types.h><sys/stat.h> |
| 原型 | mode_t umask(mode_t mask); |
| 功能 | 修改进程的文件创建掩码(umask) |
| 参数 | mask— 新的掩码值 |
| 计算公式 | • 实际文件权限 =~mask & 0666• 实际目录权限 = ~mask & 0777 |
| 返回值 | 总是成功,返回之前的掩码值 |
四、三者的核心区别
| 对比维度 | 孤儿进程 (Orphan Process) | 僵尸进程(Zombie Process) | 守护进程(Daemon Process) |
|---|---|---|---|
| 定义 | 父进程先于子进程退出,被子进程被 1 号进程收养的进程 | 子进程先退出,但父进程未调用wait/waitpid回收其 PCB,导致进程状态为 Z 的进程 | 脱离控制终端、在后台长期运行的系统服务进程(如sshd、nginx) |
| 产生原因 | 父进程意外退出或主动退出,未等待子进程 | 子进程退出后,父进程未调用wait/waitpid回收其退出状态 | 程序主动调用setsid等函数创建,脱离终端并后台运行 |
| 进程状态 | 正常运行状态,PPID=1 | 僵尸状态,标记为<defunct> | 后台运行状态,无控制终端,名称常以d结尾(如httpd) |
| 资源占用 | 占用正常进程资源(代码/数据/PCB) | 仅占用 PCB 资源(PID、退出状态),不占用代码段/数据段 | 占用正常进程资源,长期稳定运行 |
| 危害 | 无直接危害,被 1 号进程正常管理 | 大量积累会耗尽 PID 资源,导致新进程无法创建 | 无危害,是系统正常运行的必要服务(如网络服务、定时任务) |
| 处理方式 | 无需手动处理,1 号进程会自动回收其资源 | 父进程调用wait/waitpid主动回收;或终止父进程,由 1 号进程回收 | 无需处理,随系统启动而启动、终止而终止,可通过systemctl等工具管理 |
| 典型场景 | 父进程未等待子进程就退出(如脚本中后台运行的子进程) | 父进程长期运行且未处理子进程退出(如服务器程序漏洞) | 系统服务(如sshd、crond、nginx) |