Linux 进程3

进程地址空间

CPU读取数据都需要地址,在计算机中所有东西都是一种数据,包括我们的进程。

这是一个进程空间示意图,操作系统通过task_struct结构体链表来管理每一个进程,结构体里面有一个指针指向操作系统为进程开辟的一段空间,里面就是我们熟悉的栈,堆,静态区,代码段等程序的空间。

这个空间是一段连续的地址,但它不是真实的是一种映射通过页表映射到真实物理内存的一个方便的映射关系。所以其实在真实的物理内存中进程与其数据的存放不一定是连续的,只是通过了页表的映射方式来让进程的空间地址看起来是连续的而已,这个叫做虚拟内存空间。

这一段代码,定义了一个全局的变量val并在子进程中修改为100,子进程在linux中会发生写时拷贝即在修改的时候对其进行拷贝再修改所以我们在打印的时候看到父子进程的val值不同是正常的,但是这里的地址也是相同的。真实内存中一个地址对应一个字节,同一个地址有两个不同的值是不可能的,所以我们可以确定在程序内这个地址用的也是虚拟地址,而其相同是因为子进程将包括页表在内的信息都复制下来了,但是映射的物理内存空间是不同的。就是相同的页表相同的地址但是对应着不同的内存单元所以就发生两个不同的值。

fork函数

平时使用计算机我们可能同时看着视频,开着游戏,然后又在工作,那么这些都是一个程序,但是这些程序却能同时运行,这是一种CPU的并发或者并行处理多个事务的能力。其实不止上面的,就我们打开一个视频APP点开一个视频也是需要下载和播放这两个工作同时发生的,一个APP就可以看作是 一个程序那么这个两个同时发生的事件是不可能在一个进程里的,因为我们的代码都是从上到下依次执行语句的一定会有先后顺序,所以这里介绍一个系统调用函数fork就可以让我们做到一个程序同时执行两个事务。

fork函数是一个系统调用函数,在程序中可以为当前进程创建一个子程序,子程序是继承自当前程序的所有信息。所以上面进程地址空间中的虚拟地址都是相同的。

当我们调用了fork函数之后当前程序会被挂起,跳转到内核程序中(因为fork是一个系统调用函数),当轮到当前进程的时间片的时候,就会在内核中创建一个进程,在linux中就是创建一个进程PCB这个PCB基本上就是复制的父进程的,然后赋予子进程ID。一般创建一个进程系统会给分配一段进程地址空间但是这个是不分配的直接调用父进程的为了节省消耗提升效率,只有我们执行下去将里面的一些数据进行修改的时候系统才会进行数据的拷贝并分配一块新的地址空间给子进程(这是写时拷贝)。若是整个进程结束都没有对数据进行修改,那么这个拷贝就不会发生,父子进程会一直公用一段空间。

fork()的返回值类型为pid_t是一个宏其实就是一个int类型,若是返回的-1表示进程创建失败,若是为0表示当前进程为子进程,若是大于0表示当前进程是父进程。是否很奇怪,我们创建的进程到哪里去了呢,父进程又是怎么去管理呢?

当我们进入fork函数之后就不再在程序内部而是在内核程序中了,这时内核创建了一个进程PCB链接入进程队列中,这时候还没返回到调用fork的进程中但是已经是有两个进程在了,而且两个进程在同一行中返回接收fork的返回值,这时已经是两个并发或者并行运行的进程了,所以接下来的所有代码父子进程都会继续执行。而我们分辨父子进程的方式就是返回值,父进程会返回子进程的PID以方便对子进程进行管理,一般就是接收子进程的退出信息。若是父进程比子进程先结束那么子进程会由父进程的父进程即祖宗进程所继承,我们以命令行启动进程为例就是bash进程会继承子进程称为子进程新的父进程。若是子进程先于父进程结束会给父进程返回一个退出码,父进程读取退出码就能只能子进程是完成任务退出的还是出异常退出的,若是父进程一直没有接收那么子进程就会成为僵尸进程一直占用资源不会释放PCB和地址空间导致内存泄漏。

exit函数

exit用于终止一个进程的函数也是一个系统调用,_exit()是直接进入内核空间执行进程终止的命令。

exit()会先执行用户定义的清理函数,将对应的缓冲区冲刷在进入内核空间执行进程终止的命令。

与return不同的是return需要在主函数中调用才是进程终止,而exit函数则是无论在那里调用都是终止当前进程,用法与return相似。

wait函数

当我们创建了子进程之后一般都需要由父进程等待子进程退出了之后并接收子进程的退出码才退出。不然就会导致孤儿进程或是僵尸进程,孤儿进程还好会由其祖宗进程继承但是出现僵尸进程的话就会导致内存泄漏影响效率,甚至无法创建新进程。

wait函数就是给父进程用于等待子进程退出的函数。

pid_t wait(int* status) 函数的参数是个输出型参数,我们在外部定义一个int型变量将其地址传递过去,此函数会将退出的信息赋给这个地址中。返回值是一个pid,是退出的进程的pid。wait函数是阻塞等待的,当执行到这条语句时会一直阻塞等待一个进程结束。

pid_t waitpid(pid_t pid,int* status, int options),函数的第一个参数是等待的进程pid,若是输入-1的话就是等待任意一个进程与wait函数的效果一样,第二个与wait函数一样,

第三个参数是等待选项即等待的方法:

WNOHANG:如果没有子进程结束,则立即返回,不阻塞。

WUNTRACED:如果子进程进入停止状态,但不是由于接收到信号而停止,则立即返回其状态。

WCONTINUED:如果子进程继续(发送SIGCONT),则返回其状态。

这些参数是宏,若是我们在optins的位置输入0的话就会成为阻塞等待与wait函数一样。输入WNOHANG的话当执行到这条语句但是没有以结束但还没释放的进程就会立即返回0,并不会一直阻塞。输入WUNTRACED则是当有进程停止或者结束可能是接收到sigstop的信号或者等待资源等信号都会返回并返回此进程pid就不是只当进程结束才会返回。WCONTINUED 这个选项其实没什么用只是检测子进程是否被暂停后又被唤醒,若是的话调用WIFCONTINUED(status)会返回一个ture。

status参数

wait函数的参数是一个输出型参数,输出的信息如上图是一个位图形式的,整形的后十六位不使用只用前十六位,若是进程是正常结束的会有一个退出码退出码保存在第9到16位上,若是非正常退出则无退出码信息而是前8位保存终止信号的信息。core dump则是代表的core dump文件,若是进程是异常终止即由终止信号终止的系统可以保存进程的数据会创建一个core dump文件来存放一般都在当前目录下,若是此位为一则是创建了此文件,这叫核心转储。

exec进程程序替换

使用fork创建了一个子进程之后父子进程公用进程代码的,两个都是相同的那么如果我是需要执行一些其他的任务呢,若是将全部任务都放在一份代码中就会十分臃肿这份代码,所以我们需要使用进程程序替换让子进程换成另外一份代码去执行,这就是exec类函数的作用

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[]);

exec函数共有5个不过这五个都是调用的execve函数实现的,execve函数是真正的系统调用,这些都是对execve函数的封装。参数不同就意味这功能会有些许的差异。

l(list) : 表示参数采用列表

v(vector) : 参数用数组

p(path) : 有p自动搜索环境变量PATH

e(env) : 表示自己维护环境变量

这里用execl举例,使用的是列表形式的,第一个参数是替换的进程的路径,第二个是进程名,后面的是选项,最后以NULL结尾。我们可以理解为在命令行中输入的命令,实际上我们的bash程序也是这么实现的。

 #include int main() 
{ 
    char *const argv[] = {"ps", "-ef", NULL}; 

    char *const envp[] = {"PATH=/bin:/usr/bin", "TERM=console", NULL}; 

    execl("/bin/ps", "ps", "-ef", NULL);  

    execlp("ps", "ps", "-ef", NULL);  // 带p的,可以使用环境变量PATH,无需写全路径
    execle("ps", "ps", "-ef", NULL, envp); // 带e的,需要自己组装环境变量
    execv("/bin/ps", argv);   
    execvp("ps", argv); //带p的,可以使用环境变量PATH,无需写全路径
    execve("/bin/ps", argv, envp); exit(0); }// 带e的,需要自己组装环境变量 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

共享单车轨迹数据分析:以厦门市共享单车数据为例(六)

副标题:.基于POI数据的站点功能混合度探究——以厦门市为例 为了保证数据时间尺度上的一致性,我们从互联网上下载了2020年的POI数据,POI数据来源于高德地图 API平台,包括名称、大小类、地理坐标等。并将高德地图 POI数据的火星坐标 系 GCJ-0…

目标检测系列(一)什么是目标检测

目录 一、相关名词解释 二、目标检测算法 三、目标检测模型 四、目标检测应用 五、目标检测数据集 六、目标检测常用标注工具 一、相关名词解释 关于图像识别的计算机视觉四大类任务: 分类(Classification):解决“是什么&…

[附源码]宠物领养管理系统+SpringBoot

今天带来一款优秀的项目:宠物领养管理系统源码 。 系统采用的流行的前后端分离结构,内含功能包括"管理端",“用户领养端”,“宠物管理”,“权限登录”等功能。 如果您有任何问题,也请联系小编&a…

nginx+keepalived健康检查案例详解(解决nginx出现故障却不能快速切换到备份服务器的问题)

文章目录 简介配置过程前置环境请看创建健康检查脚本结果测试 简介 在我们通过nginxkeepalived实现高可用后,会发现nginx出现故障的时候keepalived并不会将虚拟ip切换到备份服务器上其原理就是nginx和keepalived是两个独立的服务,Nginx的故障状态不会触…

机器学习_神经网络_深度学习

【神经网络——最易懂最清晰的一篇文章 - CSDN App】https://blog.csdn.net/illikang/article/details/82019945?type=blog&rId=82019945&refer=APP&source=weixin_45387165 参考以上资料,可对神经网络有初步了解。接下来可参考书籍等投身实际项目中使用。 书…

羽毛球场馆预约系统,便捷管理预约

全国羽毛球运动的热度不断上升,在健身行业中掀起了一股羽毛球热潮。同时羽毛球运动的风靡,也吸引了不少人入局,各种大大小小的羽毛球馆不断出现,为大众的羽毛球喜好提供了场地。 随着互联网的发展,羽毛球馆也开始向线…

thinkPHP 8.0.4 安装

windows 上安装最新版 thinkPHP8.0.4 下载phpStudy V8.1:小皮面板安装Composer2.x,Composer是PHP的一个依赖管理工具,主要功能包括依赖管理、版本控制、自动加载、扩展开发以及集成其他工具。安装 php8.0.2 4. 网站-管理-compose&#xff0c…

【MySql】在ubuntu下安装MySql数据库

目录 查看操作系统版本 添加 MySql APT源 访问下载页面并下载发布包 安装发布包 执行安装命令 从MySql APT源更新包信息 安装MySql 执行安装命令 查看MySql状态 开启自启动 登录MySql 查看操作系统版本 rootVM-24-2-ubuntu:~# lsb_release -a No LSB modules are ava…

[翟旭发射器]python-推导式-列表list表达式练习

# 简单的列表生成 numbers00[x for x in range(1,11)] print(numbers00) # 带条件的列表生成 numbers01[x for x in range(1,11) if x%20] print(numbers01) # 带表达式的列表生成 numbers10[x**2 for x in range(1,11)] print(numbers10) # 嵌套循环的列表生成 coordinates[(x…

Python连接Kafka收发数据等操作

目录 一、Kafka 二、发送端(生产者) 三、接收端(消费者) 四、其他操作 一、Kafka Apache Kafka 是一个开源流处理平台,由 LinkedIn 开发,并于 2011 年成为 Apache 软件基金会的一部分。Kafka 广泛用于构…

CentOS 安装 JAVA环境(JDK 1.8)

镜像选择 推荐国内镜像直接下载 清华镜像 https://mirrors.tuna.tsinghua.edu.cn/Adoptium 关于重命名 AdoptOpenJDK 镜像为 Adoptium 的通知 编程宝库 http://www.codebaoku.com/jdk/jdk-index.html 这个镜像站,包含Oracle JDK、OpenJDK、AdoptOpenJDK、阿里…

视频汇聚EasyCVR视频监控平台调取接口提示“认证过期”是什么原因?

视频汇聚EasyCVR视频监控平台,作为一款智能视频监控综合管理平台,凭借其强大的视频融合汇聚能力和灵活的视频能力,在各行各业的应用中发挥着越来越重要的作用。EasyCVR平台具备强大的拓展性和灵活性,支持多种视频流的外部分发&…

【Elasticsearch】-实现图片向量相似检索

1、http请求方式 如果elasticsearch服务设置账号密码,则在请求的header中添加 Basic Auth 认证 请求方式:Post 请求地址:/index_name/_search 请求body:json格式 {"size": 10, //返回条数"min_score": 0.…

利用低代码快速搭建电商小程序之商品列表页

目标: 搭建商城的一个商品列表页面(先做静态页) 开发环境: 访问白码低代码平台:https://www.bnocode.com/ 白码的新自定义页功能(使用vue框架) 前期准备: 需要先准备商品数据表…

用 Pygame 实现一个乒乓球游戏

用 Pygame 实现一个乒乓球游戏 伸手需要一瞬间,牵手却要很多年,无论你遇见谁,他都是你生命该出现的人,绝非偶然。若无相欠,怎会相见。 引言 在这篇文章中,我将带领大家使用 Pygame 库开发一个简单的乒乓球…

Servlet入门:服务端小程序的初试(自己学习整理的资料)

目录 一.前言 二.建立基础结构​编辑 三.具体步骤 找到Tomcat文件并打开Tomcat。 在webapps中创建一个自己的文件夹。 在classes中新建一个Java文件。 在lib中导入需要的jar文件包。 配置环境变量 在Java文件的目录下打开cmd并输入 javac -d . HelloServlet.java进行…

如何设计出一个比较全面的测试用例

目录 1. 测试用例的基本要素(不需要执行结果) 2. 测试用例的给我们带来的好处 3. 用例编写步骤 4. 设计测试用例的方法 4.1 基于需求进行测试用例的设计 4.2 具体的设计方法 1.等价类 2.边界值 3.判定表(因果图) 4.正交表法 5.场景设计法 6.错误猜测…

[产品管理-33]:实验室技术与商业化产品的距离,实验室技术在商业化过程中要越过多少道“坎”?

目录 一、实验室技术 1.1 实验室研究性技术 1.2 技术发展的S曲线 技术发展S曲线的主要阶段和特点 技术发展S曲线的意义和应用 二、实验室技术商业化的路径 2.1 实验室技术与商业化产品的距离 1、技术成熟度与稳定性 - 技术自身 2、市场需求与适应性 - 技术是满足需求 …

快递物流短信API接口代码

官网:快递鸟 API参数 用户信息类 一.短信模版 1.接口说明 使用快递鸟短信功能时,预先设置好短信模板和对应的发送规则,快递鸟短信API将根据设置的好的模板和规则,进行短信的发送和反馈。 (1)仅支持Json格式。 (2)请求指令810…

org.eclipse.paho.client.mqttv3.MqttException: 无效客户机标识

需求背景 最近有一个项目,需要用到阿里云物联网,不是MQ。发现使用原来EMQX的代码去连接阿里云MQTT直接报错,试了很多种方案都不行。最终还是把错误分析和教程都整理一下。 需要注意的是,阿里云物联网平台和MQ不一样。方向别走偏了。 概念描述 EMQX和阿里云MQTT有什么区别…