【Linux】进程控制:理解什么是进程创建,进程终止,进程等待 | 进程替换
发布时间 - 2025-07-23 00:00:00 点击率:次一. 进程创建
fork函数用于创建新进程,生成的进程称为子进程,而调用fork的进程称为父进程。
fork函数的声明位于头文件 中。
在创建子进程时,系统会为子进程分配新的内存块和内核数据结构,并将父进程的部分数据结构内容复制到子进程中。子进程随后被添加到系统的进程列表中。fork函数执行后,调度器开始调度新创建的进程。
关于fork函数的返回值:
- 子进程接收到返回值0。
- 父进程接收到子进程的进程ID(PID)。
- 如果创建失败,fork函数返回-1。
子进程和父进程共享fork函数之后的代码。
实例演示:
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函数的头文件是。
返回值:
- 成功返回被等待进程的PID。
- 失败返回-1。
参数:
- 输出型参数,用于获取子进程的退出状态。如果不关心,可以设置为NULL。
wait等待任意一个子进程。
实例:
#include#include 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
# 操作系统
# ai
# 为什么
# NULL
# 全局变量
# int
# 数据结构
# 返回值
# 我是一个
# 错误码
# 错误信息
# 我是
# 并将
# 可以使用
# 是一个
# 头文件
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
Android 常见的图片加载框架详细介绍
iOS正则表达式验证手机号、邮箱、身份证号等
清除minerd进程的简单方法
Linux系统运维自动化项目教程_Ansible批量管理实战
laravel怎么使用数据库工厂(Factory)生成带有关联模型的数据_laravel Factory生成关联数据方法
Python正则表达式进阶教程_复杂匹配与分组替换解析
laravel怎么为应用开启和关闭维护模式_laravel应用维护模式开启与关闭方法
活动邀请函制作网站有哪些,活动邀请函文案?
Laravel怎么创建控制器Controller_Laravel路由绑定与控制器逻辑编写【指南】
JS弹性运动实现方法分析
怎么制作网站设计模板图片,有电商商品详情页面的免费模板素材网站推荐吗?
Laravel如何使用Laravel Vite编译前端_Laravel10以上版本前端静态资源管理【教程】
如何在Windows环境下新建FTP站点并设置权限?
Linux虚拟化技术教程_KVMQEMU虚拟机安装与调优
html5如何实现懒加载图片_ intersectionobserver api用法【教程】
深圳网站制作公司好吗,在深圳找工作哪个网站最好啊?
Laravel模型事件有哪些_Laravel Model Event生命周期详解
惠州网站建设制作推广,惠州市华视达文化传媒有限公司怎么样?
Python面向对象测试方法_mock解析【教程】
创业网站制作流程,创业网站可靠吗?
html5的keygen标签为什么废弃_替代方案说明【解答】
使用spring连接及操作mongodb3.0实例
linux写shell需要注意的问题(必看)
Laravel如何配置.env文件管理环境变量_Laravel环境变量使用与安全管理
手机怎么制作网站教程步骤,手机怎么做自己的网页链接?
Laravel怎么实现验证码(Captcha)功能
广州网站制作公司哪家好一点,广州欧莱雅百库网络科技有限公司官网?
Laravel Debugbar怎么安装_Laravel调试工具栏配置指南
Laravel如何实现邮件验证激活账户_Laravel内置MustVerifyEmail接口配置【步骤】
三星网站视频制作教程下载,三星w23网页如何全屏?
网站广告牌制作方法,街上的广告牌,横幅,用PS还是其他软件做的?
免费网站制作appp,免费制作app哪个平台好?
nginx修改上传文件大小限制的方法
Win11怎么查看显卡温度 Win11任务管理器查看GPU温度【技巧】
韩国网站服务器搭建指南:VPS选购、域名解析与DNS配置推荐
JavaScript实现Fly Bird小游戏
Laravel项目结构怎么组织_大型Laravel应用的最佳目录结构实践
Python结构化数据采集_字段抽取解析【教程】
如何安全更换建站之星模板并保留数据?
用v-html解决Vue.js渲染中html标签不被解析的问题
Windows10如何更改计算机工作组_Win10系统属性修改Workgroup
Edge浏览器提示“由你的组织管理”怎么解决_去除浏览器托管提示【修复】
高性价比服务器租赁——企业级配置与24小时运维服务
香港服务器建站指南:外贸独立站搭建与跨境电商配置流程
如何在景安服务器上快速搭建个人网站?
网页设计与网站制作内容,怎样注册网站?
EditPlus中的正则表达式 实战(2)
Laravel如何使用Socialite实现第三方登录?(微信/GitHub示例)
如何在万网主机上快速搭建网站?
如何用PHP快速搭建高效网站?分步指南


