进程控制:进程的创建、终止、阻塞、唤醒、切换等生命周期管理操作
在操作系统中,进程控制是指对进程的创建、终止、阻塞、唤醒、切换等生命周期管理操作。在 Unix/Linux 系统中,主要通过一系列系统调用来实现进程控制,以下是核心概念和常用系统调用的详解:
一、进程创建
进程创建是进程控制的基础,通过父进程创建子进程实现。
1. fork()
系统调用
- 功能:创建一个与父进程几乎完全相同的子进程(复制父进程的地址空间、文件描述符等)。
- 特点:
- 调用一次,返回两次(父进程返回子进程 PID,子进程返回 0)。
- 子进程与父进程并发执行,执行顺序不确定。
- 示例:
#include <stdio.h> #include <unistd.h>int main() {pid_t pid = fork();if (pid < 0) {// 错误处理perror("fork failed");return 1;} else if (pid == 0) {// 子进程逻辑printf("子进程: PID = %d, 父进程 PID = %d\n", getpid(), getppid());} else {// 父进程逻辑printf("父进程: 子进程 PID = %d\n", pid);// 等待子进程结束(避免僵尸进程)wait(NULL);}return 0; }
2. exec
系列函数
- 功能:在当前进程中加载并执行新的程序(替换进程的代码段、数据段等,PID 不变)。
- 常用函数:
execl()
、execv()
、execle()
、execvp()
等。 - 示例:
// 子进程中执行新程序(如 "/bin/ls") if (pid == 0) {execl("/bin/ls", "ls", "-l", NULL); // 执行 ls -l 命令perror("execl failed"); // 若执行失败才会执行exit(1); }
二、进程终止
进程终止是指进程完成任务后退出或异常终止。
1. 正常终止方式
exit(status)
:结束进程并释放资源,status
为退出状态码(父进程可通过wait()
获取)。_exit(status)
:直接终止进程,不刷新标准 I/O 缓冲区(更底层)。- 主函数
main()
返回(等价于exit(return_value)
)。
2. 异常终止方式
- 信号终止(如
Ctrl+C
发送SIGINT
信号)。 - 调用
abort()
函数(发送SIGABRT
信号)。
三、进程等待
父进程通过等待子进程结束,回收子进程资源(避免僵尸进程)。
1. wait()
函数
- 功能:阻塞等待任意一个子进程结束,回收其资源。
- 示例:
#include <sys/wait.h>int status; pid_t child_pid = wait(&status); // 阻塞等待子进程// 判断子进程退出状态 if (WIFEXITED(status)) {printf("子进程正常退出,状态码: %d\n", WEXITSTATUS(status)); } else if (WIFSIGNALED(status)) {printf("子进程被信号终止,信号值: %d\n", WTERMSIG(status)); }
2. waitpid()
函数
- 功能:更灵活的等待方式,可指定等待特定 PID 的子进程,支持非阻塞模式。
- 示例:
// 等待 PID 为 child_pid 的子进程,非阻塞模式 pid_t result = waitpid(child_pid, &status, WNOHANG); if (result == 0) {// 子进程尚未结束 } else if (result == child_pid) {// 子进程已结束,处理退出状态 }
四、进程阻塞与唤醒
- 阻塞:进程因等待某事件(如 I/O 完成、信号)暂时停止运行,进入阻塞状态。
- 唤醒:当等待的事件发生时,进程从阻塞状态转为就绪状态,等待 CPU 调度。
- 实现方式:通过系统调用(如
sleep()
、wait()
)或信号机制触发。
五、进程标识符(PID)
- 每个进程有唯一的 PID(进程 ID),父进程的 PID 称为 PPID。
- 特殊 PID:
- PID=0:内核进程(调度进程)。
- PID=1:
init
进程(所有进程的祖先,负责启动和管理系统)。
- 相关函数:
getpid()
:获取当前进程 PID。getppid()
:获取父进程 PID。
六、僵尸进程与孤儿进程
-
僵尸进程:子进程已终止,但父进程未调用
wait()
回收其资源,子进程状态变为Z(Zombie)
。- 危害:占用系统进程表项,耗尽资源。
- 解决:父进程及时调用
wait()
或waitpid()
。
-
孤儿进程:父进程先于子进程终止,子进程被
init
进程(PID=1)收养。- 特点:
init
进程会自动回收孤儿进程资源,无危害。
- 特点:
总结
进程控制的核心是通过 fork()
创建进程、exec
系列函数加载新程序、wait()
/waitpid()
回收子进程资源,以及 exit()
终止进程。理解这些机制是掌握 Unix/Linux 进程管理的基础,也是实现多任务并发的关键。