fork函数用于创建新进程,生成的进程称为子进程,而调用fork的进程称为父进程。
fork函数的声明位于头文件 <unistd.h> 中。
在创建子进程时,系统会为子进程分配新的内存块和内核数据结构,并将父进程的部分数据结构内容复制到子进程中。子进程随后被添加到系统的进程列表中。fork函数执行后,调度器开始调度新创建的进程。
关于fork函数的返回值:
子进程和父进程共享fork函数之后的代码。
立即进入“豆包AI人工智官网入口”;
立即学习“豆包AI人工智能在线问答入口”;

实例演示:
int main() {
printf("before: pid: %d\n", getpid());
pid_t id = fork();
printf("after:\n");
if (id == 0) {
// 子进程
printf("我是子进程 pid: %d ppid: %d\n", getpid(), getppid());
} else if (id > 0) {
// 父进程
printf("我是父进程 pid: %d ppid: %d\n", getpid(), getppid());
} else {
printf("出错\n");
}
return 0;
}
进程终止的情况有三种:
常用的进程退出方法包括:
returnexit_exit父进程会关心子进程的运行情况。子进程在退出时会变成僵尸进程,需要父进程回收。
父进程期望获得子进程退出的信息,包括:
可以使用以下命令查看最后一次进程退出的退出码:
echo $?
我们可以打印每个错误码对应的错误信息:
int main() {
for (int i = 0; i < 10; i++) {
printf("错误码 %d 对应的错误信息是:%s\n", i, strerror(i));
}
return 0;
}
错误码为0时,表示代码正常执行完毕,因此主函数中的return通常是return 0。我们也可以设计一套自定义的错误码体系。
exit和_exit都可以退出进程,但exit在退出前会执行额外的工作:
atexit或on_exit定义的清理函数。_exit。而_exit是直接退出进程,不处理缓冲区。因此,通常推荐使用exit函数来退出进程。

进程等待是通过系统调用wait或waitpid来检测和回收子进程的状态。
为什么需要进程等待?
父进程通过调用wait或waitpid来回收僵尸进程。
wait函数:

wait函数的头文件是<sys/wait.h>。
返回值:
参数:
wait等待任意一个子进程。
实例:
#include <sys/wait.h>
#include <unistd.h>
void Run() {
int cnt = 5;
while (cnt) {
printf("我是一个子进程 pid: %d ppid: %d\n", getpid(), getppid());
cnt--;
sleep(1);
}
}
int main() {
pid_t id = fork();
if (id == 0) {
// 子进程
Run();
exit(0);
} else if (id > 0) {
// 父进程
int cnt = 10;
while (cnt) {
printf("我是一个父进程 pid: %d ppid: %d\n", getpid(), getppid());
cnt--;
sleep(1);
}
pid_t ret = wait(NULL);
} else {
printf("出错\n");
}
return 0;
}可以使用以下指令查看运行时进程的变化:
while :; do ps ajx | head -1 && ps ajx | grep testwait | grep -v grep; sleep 1; echo "------------------------"; done
waitpid函数:

waitpid函数有三个参数:
pid:pid = -1等待任何一个子进程,与wait等效;pid > 0等待其进程ID与pid相等的子进程。status:WIFEXITED(status)若为正常终止子进程返回的状态,则为真;WEXITSTATUS(status)若WIFEXITED非零,提取子进程退出码。options:WNOHANG若pid指定的子进程没有结束,则waitpid()函数返回0,不予以等待;若正常结束,则返回该子进程的ID。status是一个输出型参数,类型为int,有32个比特位,可以视为位图。低7位表示终止信号,第8位表示core dump标志,第9位到第15位表示退出状态。

获取终止信号:status & 0x7f
获取退出码:(status >> 8) & 0xff
为什么要传一个输出型参数?因为进程之间具有独立性,不能使用全局变量代替。
等待的原理:
子进程在退出时,会将退出码和终止信号写入PCB的exit_code和exit_signal变量中。等待进程时,从子进程的PCB中读取这两个变量的值,并写入到输出型变量status中,这样父进程就可以知道子进程的退出信息。
实例:
int main() {
pid_t id = fork();
if (id == 0) {
// 子进程
int cnt = 5;
while (cnt) {
printf("我是一个子进程 pid: %d ppid: %d\n", getpid(), getppid());
cnt--;
sleep(1);
}
} else if (id > 0) {
// 父进程
int status = 0;
while (1) { // 轮询
pid_t ret = waitpid(-1, &status, WNOHANG); // 非阻塞
if (ret > 0) {
printf("子进程退出,等待成功\n");
break;
} else if (ret == 0) {
printf("你先等等,子进程还没有退出....\n");
sleep(1);
} else {
printf("等待失败\n");
break;
}
}
return 0;
}
}
在理解进程替换之前,我们先看看如何使用进程替换。操作系统提供了以下进程替换函数:

这些函数如果调用成功,则加载新的程序从启动代码开始执行,不再返回。如果调用失败,则返回-1。因此,exec函数只有失败的返回值,没有成功的返回值。
参数的含义:
l(list):表示参数采用列表形式。v(vector):参数用数组形式。p(path):有p自动搜索环境变量PATH。e(env):表示自己维护环境变量。
以上就是【Linux】进程控制:理解什么是进程创建,进程终止,进程等待 | 进程替换的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号