当前位置: 首页 > news >正文

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的,需要自己组装环境变量 

相关文章:

Linux 进程3

进程地址空间 CPU读取数据都需要地址,在计算机中所有东西都是一种数据,包括我们的进程。 这是一个进程空间示意图,操作系统通过task_struct结构体链表来管理每一个进程,结构体里面有一个指针指向操作系统为进程开辟的一段空间&am…...

R语言机器学习遥感数据处理与模型空间预测技术及实际项目案例分析

随机森林作为一种集成学习方法,在处理复杂数据分析任务中特别是遥感数据分析中表现出色。通过构建大量的决策树并引入随机性,随机森林在降低模型方差和过拟合风险方面具有显著优势。在训练过程中,使用Bootstrap抽样生成不同的训练集&#xff…...

shell linux cut 切割字符串

shell linux 切割字符串 在Shell脚本中,可以使用内置的cut命令来切割字符串。cut命令主要有三个选项 -c、-f和-d,分别表示按字符、按字段和指定分隔符来切割字符串。 按字符切割: echo "Hello World" | cut -c 1-5 # 输出&#…...

golang学习笔记31——golang 怎么实现枚举

推荐学习文档 golang应用级os框架,欢迎stargolang应用级os框架使用案例,欢迎star案例:基于golang开发的一款超有个性的旅游计划app经历golang实战大纲golang优秀开发常用开源库汇总想学习更多golang知识,这里有免费的golang学习笔…...

fastadmin本地安装插件提示”请从官网渠道下载插件压缩包(code:2)(code:1)“

这个问题主要是在fastadmin中为了保证安全性,不让你进行本地的一个安装(离线安装) 解决办法就是去把相应的代码注释掉,把相应的权限开启。 具体步骤 1.在后台的application\config.php文件下; 将这个unknownsources的…...

STM32基础学习笔记-Timer定时器面试基础题5

第五章、TIMER 常见问题 1、基本概念:什么是定时器 ?作用 ?分类 ? 2、时基单元 ?组成 ?计数模式 ?溢出条件 ? 溢出时间计算 ? 3、systick原理 ?代码讲解 &…...

CSS06-元素显示模式、单行文字垂直居中

一、什么是元素显示模式 1-1、块级元素 1-2、行内元素 1-3、行内块元素 1-4、小结 二、元素显示模式转换 三、单行文字垂直居中 CSS 没有给我们提供文字垂直居中的代码,这里我们可以使用一个小技巧来实现。 解决方案: 让文字的行高等于盒子的高度,就可…...

【车联网安全】车端网络攻击及检测的框架/模型

参考标准: 《汽车数据安全管理若干规定(试行)》ISO/SAE 21434《道路车辆 网络安全工程》威胁分析和风险评估(TARA)ISO/DIS 24089R155法规的国标转换:《汽车整车信息安全技术要求》(UN R155&…...

58.【C语言】内存函数(memcpy函数)

目录 1.memcpy *简单使用 翻译: *模拟实现 注意事项: *例题 1.memcpy *简单使用 memcpy:memory copy cplusplus的介绍 点我跳转 翻译: 函数 memcpy void * memcpy ( void * destination, const void * source, size_t num ); 复制内存块 直接从source指向的位置复制num…...

rust一些通用编程的概念

rust一些通用编程的概念 官网文档数据类型 - Rust 程序设计语言 中文版 (rustwiki.org) 变量,数据类型,条件判断,循环 变量 rust中变量的可变性是值得注意的 例如: fn main(){let number 1;number 2;println!("the number is {}&quo…...

SpringBoot基础知识

谈一谈你对SpringBoot的理解,它有哪些特性(优点)? SpringBoot用来快速开发Spring应用的一个脚手架,其目的是用来简化新Spring应用的初始搭建以及开发过程。 优点: 简化配置:提供了很多内置的…...

ubuntu配置libtorch CPU版本

配置环境:Ubuntu 20.04Date:2024 / 08 1、下载最新版本的libtorch wget https://download.pytorch.org/libtorch/nightly/cpu/libtorch-shared-with-deps-latest.zip unzip libtorch-shared-with-deps-latest.zip2、创建一个C工程文件夹,目…...

Docker MySql 数据备份、恢复

docker-compose.yaml实例 version: 3.8 services:db:image: mysql:9.0.1environment:MYSQL_ROOT_PASSWORD: 123456MYSQL_DATABASE: dataMYSQL_USER: dataMYSQL_PASSWORD: 123456MYSQL_ROOT_HOST: % 1、备份 docker exec -it <容器名称> /usr/bin/mysqldump -u root -p12…...

django项目添加测试数据的三种方式

文章目录 自定义终端命令Faker添加模拟数据基于终端脚本来完成数据的添加编写python脚本编写shell脚本执行脚本需要权限使用shell命令来完成测试数据的添加 添加测试数据在工作中一共有三种方式&#xff1a; 可以根据django的manage.py指令进行[自定义终端命令]可以采用第三方…...

用Python提取PDF表格到Excel文件

在对PDF中的表格进行再利用时&#xff0c;除了直接将PDF文档转换为Excel文件&#xff0c;我们还可以提取PDF文档中的表格数据并写入Excel工作表。这样做可以避免一些不必要的文本和格式带来的干扰&#xff0c;获得更易于分析和处理的表格数据&#xff0c;并方便进行更多的格式设…...

Java基础|多线程:多线程分页拉取

前言&#xff1a; 通常我们都会遇到分页拉取的需求&#xff0c;比如与第三方系统同步数据&#xff0c;定时拉取全量数据做缓存&#xff0c;下面我们简单介绍下多线程分页写法 需求&#xff1a; 全量同步第三方系统数据&#xff0c;并在全部数据同步完后&#xff0c;统一做缓存…...

Android RecyclerView 实现 GridView ,并实现点击效果及方向位置的显示

效果图 一、引入 implementation com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.30 二、使用步骤 1.Adapter public class UnAdapter extends BaseQuickAdapter<UnBean.ResultBean, BaseViewHolder> {private int selectedPosition RecyclerView.NO_POSITIO…...

Centos中dnf和yum区别对比

dnf和yum是两种不同的包管理工具&#xff0c;它们各自具有独特的特点和优势&#xff0c;主要用于在Linux系统上安装、更新和卸载软件包。以下是dnf和yum之间的主要区别&#xff1a; 1. 依赖关系解决 dnf&#xff1a;dnf在处理依赖关系方面表现出更强的能力。它能够更高效地解…...

CVPT: Cross-Attention help Visual Prompt Tuning adapt visual task

论文汇总 当前的问题 图1:在VTAB-1k基准测试上&#xff0c;使用预训练的ViT-B/16模型&#xff0c;VPT和我们的CVPT之间的性能和Flops比较。我们将提示的数量分别设置为1、10、20、50,100,150,200。 如图1所示&#xff0c;当给出大量提示时&#xff0c;VPT显示了性能的显著下降…...

基于双向 LSTM 和 CRF 的序列标注模型

基于双向 LSTM 和 CRF 的序列标注模型 在自然语言处理中,序列标注是一项重要的任务,例如命名实体识别、词性标注等。本文将介绍如何使用 Keras 构建一个基于双向 LSTM 和 CRF 的序列标注模型。 一、引言 序列标注任务要求为输入序列中的每个元素分配一个标签。传统的方法可…...

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…...

7.4.分块查找

一.分块查找的算法思想&#xff1a; 1.实例&#xff1a; 以上述图片的顺序表为例&#xff0c; 该顺序表的数据元素从整体来看是乱序的&#xff0c;但如果把这些数据元素分成一块一块的小区间&#xff0c; 第一个区间[0,1]索引上的数据元素都是小于等于10的&#xff0c; 第二…...

【杂谈】-递归进化:人工智能的自我改进与监管挑战

递归进化&#xff1a;人工智能的自我改进与监管挑战 文章目录 递归进化&#xff1a;人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管&#xff1f;3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...

R语言AI模型部署方案:精准离线运行详解

R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...

Docker 运行 Kafka 带 SASL 认证教程

Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明&#xff1a;server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...

服务器硬防的应用场景都有哪些?

服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式&#xff0c;避免服务器受到各种恶意攻击和网络威胁&#xff0c;那么&#xff0c;服务器硬防通常都会应用在哪些场景当中呢&#xff1f; 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...

linux arm系统烧录

1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 &#xff08;忘了有没有这步了 估计有&#xff09; 刷机程序 和 镜像 就不提供了。要刷的时…...

ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放

简介 前面两期文章我们介绍了I2S的读取和写入&#xff0c;一个是通过INMP441麦克风模块采集音频&#xff0c;一个是通过PCM5102A模块播放音频&#xff0c;那如果我们将两者结合起来&#xff0c;将麦克风采集到的音频通过PCM5102A播放&#xff0c;是不是就可以做一个扩音器了呢…...

(转)什么是DockerCompose?它有什么作用?

一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用&#xff0c;而无需手动一个个创建和运行容器。 Compose文件是一个文本文件&#xff0c;通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...

GitFlow 工作模式(详解)

今天再学项目的过程中遇到使用gitflow模式管理代码&#xff0c;因此进行学习并且发布关于gitflow的一些思考 Git与GitFlow模式 我们在写代码的时候通常会进行网上保存&#xff0c;无论是github还是gittee&#xff0c;都是一种基于git去保存代码的形式&#xff0c;这样保存代码…...