📘 目录
- 什么是进程控制?
- 进程的创建:fork 与 exec
- 父子进程与进程关系
- 进程终止与退出码
- 僵尸进程与孤儿进程
- 等待与回收子进程(wait/waitpid)
- 进程组与会话(Process Group & Session)
- 守护进程(Daemon)的实现
- 信号机制:控制进程的利器
- 实用案例与命令实践
- 小结与思考
1️⃣ 什么是进程控制?
进程控制是指操作系统对**进程生命周期(创建→运行→阻塞→退出)**进行管理与调度的所有操作行为,开发者也可以通过系统调用来创建、控制、终结进程。
2️⃣ 进程的创建:fork()
与 exec()
Linux 创建新进程最经典的方法就是使用 fork()
:
pid_t pid = fork();
if (pid == 0) {
// 子进程逻辑
} else if (pid > 0) {
// 父进程逻辑
} else {
// 创建失败
}
fork()
复制父进程的内存空间,但采用**写时复制(Copy-on-Write)**机制。
要在子进程中运行另一个程序,应配合 exec()
使用:
execl("/bin/ls", "ls", "-l", NULL);
常见的 exec
家族函数包括:
execl
、execp
、execv
、execve
等
3️⃣ 父子进程与进程关系
- 每个进程有一个父进程(通过
getppid()
获取) - 父进程通过
wait()
系列函数来收尸(回收子进程) - 父进程终止后,子进程会被
init
或systemd
收养,成为孤儿进程
4️⃣ 进程终止与退出码
子进程可以通过 exit()
正常终止,返回退出码,供父进程获取:
exit(0); // 表示正常退出
exit(1); // 非正常退出
父进程使用如下方式获取退出状态:
int status;
wait(&status);
if (WIFEXITED(status)) {
printf("Exit code: %d\n", WEXITSTATUS(status));
}
5️⃣ 僵尸进程与孤儿进程
- 僵尸进程(Zombie):子进程已退出,但父进程未回收,系统保留其 PID 和状态信息
- 孤儿进程(Orphan):父进程提前终止,子进程由
init
或systemd
接管
解决僵尸进程的方式:
- 使用
wait()
或waitpid()
回收 - 使用信号
SIGCHLD
通知父进程回收子进程
6️⃣ 等待与回收子进程:wait()
与 waitpid()
wait()
:等待任意一个子进程结束waitpid(pid, &status, options)
:指定等待某个子进程,更灵活
waitpid(child_pid, &status, 0); // 阻塞等待指定子进程结束
可选项包括:
WNOHANG
:非阻塞模式WUNTRACED
:监听停止的子进程
7️⃣ 进程组与会话(pgid/session)
Linux 中进程有组织结构:
概念 | 说明 |
---|---|
进程组(PGID) | 一组相关进程共享控制机制,常用于 Shell 中控制前台/后台 |
会话(SID) | 会话是一组进程组,可表示一个登录会话或终端控制会话 |
创建新会话的函数:
setsid(); // 创建新会话并脱离终端控制
8️⃣ 守护进程的实现(Daemon)
守护进程是后台运行的独立服务程序(如 sshd
, cron
, nginx
):
基本实现步骤:
fork()
创建子进程,父进程退出setsid()
创建新会话,脱离终端- 修改工作目录、umask,关闭标准输入输出
- 运行服务主循环
daemon(0, 0); // 快速实现守护进程化(glibc 提供)
9️⃣ 信号机制:控制进程的利器
信号是进程之间或内核向进程发送的异步通知:
信号 | 意义 |
---|---|
SIGINT | Ctrl+C 终止程序 |
SIGTERM | 优雅终止 |
SIGKILL | 强制终止,不能捕获 |
SIGCHLD | 子进程结束通知父进程 |
SIGHUP | 终端挂断 |
信号处理函数:
void handler(int sig) {
printf("Received signal: %d\n", sig);
}
signal(SIGINT, handler);
🔨 10️⃣ 实用案例与命令实践
查看所有进程:
ps -ef
创建后台进程:
./myprogram &
查找特定进程 PID:
pidof nginx
杀死进程:
kill -9 <PID>
使用 C 创建子进程:
if (fork() == 0) {
execlp("ls", "ls", "-la", NULL);
exit(1);
}
🧠 11️⃣ 小结与思考
Linux 中的“进程控制”是操作系统最核心的模块之一。掌握它,意味着你可以:
- 高效调度任务
- 构建后台服务与守护进程
- 避免僵尸进程和资源泄露
- 编写稳定的服务端程序
📚 推荐阅读
- 《APUE:UNIX 环境高级编程》Ch8:进程控制
- 《Linux高性能服务器编程》Ch3:进程模型
- man 手册:
man 2 fork
,man 2 exec
,man 2 wait
,man 7 signal
发表回复