Linux:进程:进程控制

进程创建

在Linux中我们使用fork函数创建新进程:

fork函数

fork函数是Linux中的一个系统调用,用于创建一个新的进程,创建的新进程是原来进程的子进程

返回值:如果子进程创建失败,返回值是-1。如果子进程创建成功,对于父进程而言,fork的返回值是子进程的pid(子进程的进程号);对于子进程而言,fork的返回值是0。

让父子进程分别打印fork函数的返回值和自己的PID:

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>int main()
{pid_t pid;      //parent_idpid_t cid;      //child_pidprintf("Before fork Process id: %d\n", getpid());cid = fork();printf("After fork, Process id: %d\n", getpid());printf("fork_function return: %d\n", cid);sleep(5);return 0;
}

实验结果:

调用fork后,内核中的fork代码会执行:

• 分配新的内存块和内核数据结构给⼦进程

• 将⽗进程部分数据结构内容拷⻉⾄⼦进程

• 将⼦进程添加到系统进程列表当中

• fork返回,调度器开始调度

子进程被创建好后,父子进程会并发执行后续代码

父子进程内存空间独立

上文说到,fork函数会把父进程的代码和数据拷贝给子进程,以此来保证进程之间的独立性,但实际上,为了节省内存空间和提高运行效率,只有当子进程的代码和数据发生变化时,才会为子进程开辟一块内存空间,并将父进程的代码和数据拷贝给子进程,这被称为写时拷贝

而在写时拷贝之前,父子进程的虚拟地址相同,并且通过页表映射后指向同一处物理地址

而在写时拷贝之后,父子进程的虚拟地址仍然相同,只是会映射到不同的物理地址

进程终止

进程终⽌的本质是释放进程申请的相关内核数据结构和对应的数据和代码。

进程退出的三种情况:

1.代码运⾏完毕,结果正确

2.代码运⾏完毕,结果不正确

3. 代码异常终⽌

为了判断进程终止是哪种情况,进程在结束时会将退出码和退出信号返回给父进程,其中,退出信号用于判断进程是否异常,退出码用于判断进程运行结果是否正确

如何获取退出码和退出信号,我们在进程等待部分再做介绍,这里先介绍常见的退出码:

可以使⽤strerror函数来获取退出码对应的描述。

返回不同的退出码:

1.使用 return n

2.使用void exit(int status)或void _exit(int status),二者区别如下:

return n和exit(n)等效

进程等待

进程等待的目的:

1.检查子进程的任务执行

2.避免产生僵尸进程

进程等待的方法

wait函数

#include<sys/types.h>
#include<sys/wait.h>
pid_t wait(int* status);

返回值:

成功返回被等待进程 pid ,失败返回-1 。

参数:

status:输出型参数,获取⼦进程退出码 , 不关⼼则可以设置成为 NULL

一个父进程可能有多个子进程,而wait函数等待的是任意子进程

因此,推荐使用waitpid函数:

 pid_ t waitpid(pid_t pid, int *status, int options);

返回值:

当正常返回的时候 waitpid 返回收集到的⼦进程的进程 ID ;

如果设置了选项 WNOHANG, ⽽调⽤中 waitpid 发现没有已退出的⼦进程可收集 , 则返回 0 ;

如果调⽤中出错 , 则返回-1, 这时 errno 会被设置成相应的值以指⽰错误所在;

参数:

pid :

Pid=-1, 等待任⼀个⼦进程。与 wait 等效。

Pid>0. 等待其进程 ID 与 pid 相等的⼦进程。

status: 输出型参数,为了便于调用,可以使用以下两个宏:

WIFEXITED(status): 若为正常终⽌⼦进程返回的状态,则为真。(查看进程是否是正常退出) WEXITSTATUS(status): 若 WIFEXITED ⾮零,提取⼦进程退出码。(查看进程的退出码)

options:

默认为 0 ,表⽰阻塞等待

WNOHANG: 非阻塞等待,若 pid 指定的⼦进程没有结束,则 waitpid() 函数返回 0 ,不予等待。若正常结束,则返回该⼦进程的 ID 。

status

status用于记录子进程的退出信号和退出码:

前7位为退出信号,第8位为core dump标志(不关心),9~16位为退出码

若退出信号非0,表明进程异常

若退出信号为0,表明进程正常运行

若退出码非0,表明运行结果错误

若退出码非0,表明运行结果正常

阻塞等待与非阻塞轮询等待对比

阻塞等待:

int main(){pid_t pid;pid = fork();if(pid < 0){printf("%s fork error\n",__FUNCTION__);return 1;} else if( pid == 0 ){ //childprintf("child is run, pid is : %d\n",getpid());sleep(5);exit(257);} else{int status = 0;pd_t ret = waitpid(-1, &status, 0);//阻塞式等待,等待5S printf("this is test for wait\n");if( WIFEXITED(status) && ret == pid ){printf("wait child 5s success, child return code is:%d.\n",WEXITSTATUS(status));}else{printf("wait child failed, return.\n");return 1;}}return 0;}

父进程阻塞等待成功

虽然返回的是257,但由于退出码只取8位,所以返回1:

非阻塞轮询等待:

void handler() {printf("临时任务\n");sleep(1);}int main() {pid_t pid;pid = fork();if (pid < 0) {printf("%s fork error\n", __FUNCTION__);return 1;} else if (pid == 0) {  // childprintf("child is run, pid is : %d\n", getpid());sleep(5);exit(1);} else {int status = 0;pid_t ret = 0;do {ret = waitpid(-1, &status, WNOHANG);  //⾮阻塞式等待if (ret == 0) {printf("child is running\n");}handler();} while (ret == 0);if (WIFEXITED(status) && ret == pid) {printf("wait child 5s success, child return code is :%d.\n",WEXITSTATUS(status));} else {printf("wait child failed, return.\n");return 1;}}return 0;}

可以看到父进程一边执行自己的“临时任务”,一边询问子进程是否结束,直到子进程结束,等待结束:

进程替换

我们之前虽然用fork创建了子进程,但是子进程和父进程执行的还是同样的代码,很多时候我们创建子进程就是为了去专门执行某一任务,这就需要用到进程替换,进程替换是通过特定的接⼝,把磁盘上另外的⼀个程序的代码和数据加载到调⽤原先进程的地址空间中。

替换原理

⽤fork创建⼦进程后执⾏的是和⽗进程相同的程序(但有可能执⾏不同的代码分⽀),⼦进程往往要调⽤⼀种exec函数以执⾏另⼀个程序。当进程调⽤⼀种exec函数时,该进程的⽤⼾空间代码和数据完全被新程序替换,从新程序的启动例程开始执⾏。调⽤exec并不创建新进程,所以调⽤exec前后该进程的id并未改变。

替换函数

#include <unistd.h>
int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *path, const char *arg, ...,char *const envp[]);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execve(const char *path, char *const argv[], char *const envp[]);

这些函数如果调⽤成功则加载新的程序从启动代码开始执⾏,不再返回;如果调⽤出错则返回-1 

这里把子进程替换为一个能够读入并执行命令的程序:

#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h> 
int main(int argc, char* argv[])
{pid_t id=fork();if(id==0){     char**  myargv=&argv[1];                                                                                                                                                    execvp(myargv[0],myargv);}waitpid(id,NULL,0);return 0;
}

可以看到子进程可以收集并执行命令

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/77865.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

day1-小白学习JAVA---JDK安装和环境变量配置(mac版)

JDK安装和环境变量配置 我的电脑系统一、下载JDK1、oracle官网下载适合的JDK安装包&#xff0c;选择Mac OS对应的版本。 二、安装三、配置环境变量1、终端输入/usr/libexec/java_home -V查询所在的路径&#xff0c;复制备用2、输入ls -a3、检查文件目录中是否有.bash_profile文…

Python项目--基于机器学习的股票预测分析系统

1. 项目介绍 在当今数字化时代&#xff0c;金融市场的数据分析和预测已经成为投资决策的重要依据。本文将详细介绍一个基于Python的股票预测分析系统&#xff0c;该系统利用机器学习算法对历史股票数据进行分析&#xff0c;并预测未来股票价格走势&#xff0c;为投资者提供决策…

计算机视觉与深度学习 | 基于YOLOv8与光流法的目标检测与跟踪(Python代码)

===================================================== github:https://github.com/MichaelBeechan CSDN:https://blog.csdn.net/u011344545 ===================================================== 目标检测与跟踪 关键实现逻辑检测-跟踪协作机制‌特征点选择策略‌运动…

Java集合及面试题学习

知识来源沉默王二、小林coding、javaguide 1、ArrayList list.add("66") list.get(2) list.remove(1) list.set(1,"55") List<String> listnew ArrayList<>(); 底层是动态数组 添加元素流程&#xff1a;判断是否扩容&#xf…

OSPF --- LSA

文章目录 一、OSPF LSA&#xff08;链路状态通告&#xff09;详解1. LSA通用头部2. OSPFv2 主要LSA类型a. Type 1 - Router LSAb. Type 2 - Network LSAc. Type 3 - Summary LSAd. Type 4 - ASBR Summary LSAe. Type 5 - AS External LSAf. Type 7 - NSSA External LSA 3. LSA泛…

Spring Boot 框架介绍及 Spring Boot 与 Spring 实现对比

在日常 Java Web 开发中&#xff0c;Spring 框架几乎是绕不开的技术体系。传统的 Spring 项目因其灵活强大而被广泛应用&#xff0c;但随着项目规模扩大与业务复杂度提升&#xff0c;XML 配置繁琐、部署复杂等问题逐渐显现。为此&#xff0c;Spring Boot 应运而生。 Spring Boo…

基于CNN卷积神经网络和GEI步态能量提取的视频人物步态识别算法matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 4.1 GEI步态能量提取 4.2 CNN卷积神经网络原理 5.算法完整程序工程 1.算法运行效果图预览 (完整程序运行后无水印) 2.算法运行软件版本 matlab2024b/matlab2022a 3.部分核心程序 &…

创建型模式:建造者模式

什么是建造者模式 建造者模式&#xff08;Builder Pattern&#xff09;是一种创建型设计模式&#xff0c;它将一个复杂对象的构建过程与其表示分离&#xff0c;使得同样的构建过程可以创建不同的表示。简单来说&#xff0c;建造者模式允许您一步一步创建复杂对象&#xff0c;而…

Linux `init 5` 相关命令的完整使用指南

Linux init 5 相关命令的完整使用指南—目录 一、init 系统简介二、init 5 的含义与作用三、不同 Init 系统下的 init 5 行为1. SysVinit&#xff08;如 CentOS 6、Debian 7&#xff09;2. systemd&#xff08;如 CentOS 7、Ubuntu 16.04&#xff09;3. Upstart&#xff08;如 …

RabbitMQ常见面试题回答重点

文章目录 什么是消息队列&#xff1f;为什么需要消息队列消息队列的模型消息队列常见名词如何保证消息不丢失&#xff1f;&#xff08;可靠性&#xff09;如何保证消息不重复/业务幂等性如何保证消息有序性如何处理消息堆积消息队列设计为推送还是拉取 / 推拉模式优点无法路由的…

欣佰特携数十款机器人相关前沿产品,亮相第二届人形机器人和具身智能行业盛会

2025年4月15日至16日&#xff0c;备受关注的第二届中国人形机器人与具身智能产业大会已在北京成功举行。作为国内前沿科技及产品服务领域的重要参与者&#xff0c;欣佰特科技携众多前沿产品精彩亮相&#xff0c;全方位展示了其在人形机器人与具身智能领域的创新产品。 在本次大…

Docker安装 (centos)

1.安装依赖包&#xff1a; sudo yum install -y yum-utils device-mapper-persistent-data lvm2 2.删除已有的 Docker 仓库文件&#xff08;如果有&#xff09;&#xff1a; sudo rm -f /etc/yum.repos.d/docker-ce.repo 3.添加阿里云的 Docker 仓库&#xff1a; sudo yum…

Vue接口平台学习十——接口用例页面2

效果图及简单说明 左边选择用例&#xff0c;右侧就显示该用例的详细信息。 使用el-collapse折叠组件&#xff0c;将请求到的用例详情数据展示到页面中。 所有数据内容&#xff0c;绑定到caseData中 // 页面绑定的用例编辑数据 const caseData reactive({title: "",…

服务器数据迁移指南

服务器数据迁移是将数据从一台服务器转移到另一台服务器的过程&#xff0c;可能是为了硬件升级、云迁移、数据中心搬迁或服务整合。 以下是数据迁移的关键步骤和注意事项&#xff1a; 迁移前准备 制定迁移计划 确定迁移范围(全量/增量) 评估数据量和网络带宽 制定时间表和回…

25.解决中医知识问答删除历史对话功能后端处理请求时抛出异常

ChatTest.vue:176 DELETE http://localhost:8080/api/chat/conversations/20 500 (Internal Server Error) deleteConversation ChatTest.vue:176 onClick ChatTest.vue:22 ChatTest.vue:185 删除失败 AxiosError {message: Request failed with status code 500, name: Axio…

记录seatunnel排查重复数据的案例分析

文章目录 背景分析检查现象检查B集群是否有异常&#xff0c;导致重复消费的分析同步任务 修复问题发现flink job 一直报异常修复问题 背景 使用seatunnel 同步数据从A 集群kafka 同步到B集群kafka,现象是发现两边数据不一致&#xff0c;每天10w级别会多几十条数据 分析 检查…

VSCode远程图形化GDB

VSCode远程图形化GDB 摘要一、安装VSCode1、使用.exe安装包安装VSCode2、VSCode 插件安装3、VSCode建立远程连接 二、core dump找bug1、开启core文件2、永久生效的方法3、编写测试程序4、运行结果5、查看core段错误位置6、在程序中开启core dump并二者core文件大小 三、gdbserv…

Android 中实现 GIF 图片动画

在 Android 中&#xff0c;ImageView 从 Android 9.0&#xff08;API 级别 28&#xff09; 开始原生支持 GIF 动画&#xff0c;通过 AnimatedImageDrawable 类实现。在之前的版本中&#xff0c;ImageView 并不支持直接播放 GIF 动画&#xff0c;只能显示 GIF 的第一帧。 一、 …

【c语言】指针进阶

目录 1.字符指针 2.指针数组 3.数组指针 3.1 数组指针的定义 3.2 数组指针的使用 4.数组参数&#xff0c;指针参数 4.1 一维数组传参 4.2 二维数组传参 4.3 一级指针传参 4.4 二级指针传参 5.函数指针 6.函数指针数组 6.1函数指针数组的定义 6.2 函数指针数组…

极狐GitLab 项目 API 的速率限制如何设置?

极狐GitLab 是 GitLab 在中国的发行版&#xff0c;关于中文参考文档和资料有&#xff1a; 极狐GitLab 中文文档极狐GitLab 中文论坛极狐GitLab 官网 项目 API 的速率限制 (BASIC SELF) 引入于 15.10 版本&#xff0c;功能标志为rate_limit_for_unauthenticated_projects_api_…