【Linux系统】为什么环境变量具有全局性?共享?写时拷贝优化?




在这里插入图片描述



环境变量表具有全局性的原因:


环境变量表之所以具有全局性的特征,主要是因为它们是在进程上下文中维护的,并且在大多数操作系统中,当一个进程创建另一个进程(即父进程创建子进程)时,子进程会继承其父进程的环境变量。这意味着子进程将会获得与父进程相同的环境变量表,除非在创建子进程时明确地改变了某些环境变量。

这种继承机制使得环境变量在整个程序执行期间以及在派生的子进程中保持一致性和可用性。然而,尽管环境变量在一定范围内具有“全局性”,但需要注意的是,每个进程实际上都有它自己独立的一份环境变量副本。也就是说,对某个进程中的环境变量所做的更改不会影响到其他已经存在的进程。这种设计有助于避免不同进程之间的干扰,并提供一定程度的隔离,保证了进程的独立性。




写时拷贝机制:


Linux 系统中,当一个进程创建子进程时,子进程确实会继承父进程的环境变量表,但这种继承实际上是通过一种称为 “写时拷贝”(Copy-On-Write, COW)的优化技术来实现的:

前面虽说子进程拥有一份父进程环境变量表的拷贝副本,但这句话其实没有那么准确。实际上,若子进程不修改自己的环境变量表,则子进程和父进程会同时共用同一张环境变量表,这有利于节省内存空间与提高系统效率。

如果子进程修改了自己的环境变量,则会触发系统的写时拷贝机制,系统才会为该子进程分配新的内存页面,并将原来的和父进程共享的环境变量复制到新的内存中。这样,只有在实际需要修改的情况下,才会发生真正的复制。



更加细致的理解:只读数据一般可以被共享

        在Linux系统中,环境变量通常是只读的,这意味着在多数情况下,子进程可以直接与父进程共享同一张环境变量表,而不必立即创建一份副本。只有当子进程试图修改环境变量时,系统才会触发写时拷贝(Copy-On-Write, COW)机制,为子进程分配新的内存区域,并复制必要的数据。




写时拷贝机制是不是很聪明!!:你我都不修改,就一起共用;之后谁修改了就为谁分配新的内存存放修改后的新内容。这样只有在真正修改时,才会发生真正的拷贝,大大优化了系统效率。






梳理写时拷贝机制过程


通过父进程创建子进程的例子梳理一下 写时拷贝机制的过程:


1、 创建子进程: 当一个进程通过fork()创建子进程时,子进程继承了父进程的数据段、堆和栈等内存区域,包括环境变量表。这些内存区域在开始时是共享的,意味着它们指向相同的物理内存页面。

同时这些初始共享区域都是只读的:父进程在继承页表给子进程前,会将页表条目的权限改为只读,然后才继承该页表给子进程。
在这里插入图片描述


2、修改检测: 如果子进程试图修改一个共享的内存页面(包括环境变量表),即子进程向只读数据写入时,会触发系统错误:“缺页中断”。

对于子进程写入只读数据产生的缺页中断,操作系统有两种处理情况:

  • 对代码区写入:不允许,杀掉该子进程
    • 代码区共享,程序的代码在执行时不应该被修改,防止破坏了代码的完整性,而不允许任何一方修改
  • 对数据区写入:触发写时拷贝机制,每个进程都有自己的数据副本,实现进程的数据独立性


3、写时拷贝:

  • 操作系统会为子进程分配新的内存页面。
  • 将原来的页面复制到新的内存页面中。
  • 修改后的页面指向新的内存页面,而原来的页面仍然保留不变。
  • 父进程和其他未修改的子进程仍然可以继续共享原来的内存页面。

修改的页面各自一份,未修改的部分保持不变(只读且共享)
在这里插入图片描述


简化步骤:方便记忆

  • 保存上下文数据
  • 申请内存空间(找到合适的空间,若空间不足则系统进程页面置换等操作)
  • 发生拷贝(拷贝一份待修改数据到新分配的物理内存空间)
  • 更新页表映射
  • 恢复上下文数据(恢复程序执行)



为什么存放修改数据需要先拷贝一次原数据?

明明修改数据,直接开辟空间存放我修改后的值就好,为什么需要多一步拷贝??

解释:你的写入操作 不等于 对目标区域进行覆盖操作

某些修改程序还是需要使用到历史数据的,而不是单纯的写入新数据

count++ :这句代码的底层执行过程是先保存一份旧数据,其次 count+1 ,最后返回原数据



父进程修改共享数据会不会写时拷贝?

  • 父进程创建子进程时:无论是父进程还是子进程修改共享的内存区域(如数据段中的全局变量或静态变量),都会触发写时拷贝机制,以确保数据的一致性和避免不必要的内存复制。
  • 父进程单独运行时:父进程直接修改其拥有的物理内存页面中的数据,不会触发写时拷贝机制。

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

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

相关文章

网站建设前需要搞清楚哪些问题

网站建设前需要搞清楚的问题涉及多个方面,以下是一些关键问题的概述: 明确目标和目的 企业宣传与品牌塑造:网站是企业展示形象、传播品牌的重要窗口。通过精心设计的网站界面和内容布局,可以向潜在客户传递企业的价值观、文化理念…

iOS AVAudioSession 详解【音乐播放器的配置】

前言 在 iOS 音频开发中,AVAudioSession 是至关重要的工具,它控制着应用的音频行为,包括播放、录音、后台支持和音频中断处理等。对于音乐播放器等音频需求强烈的应用,设计一个合理的 AVAudioSession 管理体系不仅能保证音频播放…

[JAVAEE] 多线程的案例(三) - 线程池

目录 一. 什么是线程池 二. 线程池的作用 三. java提供的线程池类 四. ThreadPoolExecutor的构造方法及参数理解 1. int corePoolSize: 核心线程数. 2. int maximumPoolSize: 最大线程数 核心线程数 非核心线程数 3. int keepAliveTime:非核心线程允许空闲的最大时间. …

网络通信与并发编程(六)线程、进程池与线程池

线程、进程池与线程池 文章目录 线程、进程池与线程池一、线程二、线程的相关操作2.1创建线程的两种方式2.2线程的其他操作2.3死锁现象和递归锁2.4条件2.5定时器2.6 队列与堆栈 三、进程池与线程池 一、线程 线程是指cpu上实际执行计算的单位,而进程是将计算所需资…

Leetcode刷题笔记12

HJ1 字符串最后一个单词的长度 字符串最后一个单词的长度_牛客题霸_牛客网 这里可以使用rfind(),rfind()函数从字符串的末尾向前查找第一个空格的位置。这个空格将是最后一个单词和前面的单词的分隔符。首先使用getline读取字符串,然后用rfind找到最后一…

class 36 二叉树高频题目 - 上 (不含有树形dp)

1. BFS 的两种方式 如下图, 是一个二叉树. 我们需要按照层的方式来遍历这棵树. 1.1 使用 JDK 自带的类实现(链表实现, 经典 BFS) 首先我们实现一个队列, 这个队列从头进, 从尾出.然后将根节点放入其中, 然后将放入的节点弹出,然后继续验证弹出的节点有没有左孩子, 若是有, 将…

便捷之选:微信小程序驱动的停车场管理系统

作者介绍:✌️大厂全栈码农|毕设实战开发,专注于大学生项目实战开发、讲解和毕业答疑辅导。 🍅获取源码联系方式请查看文末🍅 推荐订阅精彩专栏 👇🏻 避免错过下次更新 Springboot项目精选实战案例 更多项目…

跨境支付,哪些国产数据库能接得住?

最近有一个非常重大的事件,那就是10月22日-24日的金砖国家会议。金砖国家领导人第十六次会晤是金砖国家进一步凝聚共识、以实际行动推动“全球南方”共同发展进步的重要机遇。 酝酿已久的金砖跨境支付体系,也在这次峰会中正式推出。金砖国家的支付系统一…

国内大语言模型哪家更好用?

大家好,我是袁庭新。 过去一年,AI大语言模型在爆发式增长,呈现百家争鸣之态。国内外相关厂商积极布局,并相继推出自家研发的智能化产品。 我在工作中已习惯借助AI来辅助完成些编码、创作、文生图等任务,甚至对它们产…

【计网】从零开始认识IP协议 --- 认识网络层,认识IP报头结构

从零开始认识IP协议 1 网络层协议1.1 初步认识IP协议1.2 初步理解IP地址 2 IP协议报头3 初步理解网段划分 1 网络层协议 1.1 初步认识IP协议 我们已经熟悉了传输层中的UDP和TCP协议,接下来我们来接触网络层的协议: 网络层在计算机网络中的意义主要体现…

线段树

文章目录 1 线段树概念2 线段树操作2.1 建树2.2 区间修改2.3 区间查询2.4 练习题目 3 线段树进阶3.1 乘法线段树 * 补充:快读快写4 End 1 线段树概念 线段树 ( S e g m e n t T r e e ) (Segment\ Tree) (Segment Tree) 是 O I OI OI 中的常用算法。线段树是一种…

PHP-FPM 性能配置优化

4 核 8 G 服务器大约可以开启 500 个 PHP-FPM,极限吞吐量在 580 qps (Query Per Second 每秒查询数)左右。 Nginx php-fpm 是怎么工作的? php-fpm 全称是 PHP FastCGI Process Manager 的简称,从名字可得知&#xff…

基于SSM的冰淇淋在线购买网站【附源码】

基于SSM的冰淇淋在线购买网站 效果如下: 系统首页界面 用户登录界面 冰淇淋页面 每日秒杀页面 个人中心界面 管理员登录界面 管理员功能界面 口味管理界面 冰淇淋管理界面 每日秒杀管理界面 视频教学管理界面 研究背景 近些年,随着中国经济发展&#…

订购 Claude AI 的第二天 它独自完成 文字转语音 flask应用

图二里,删除几个无关的 chats 全程我做的工作:向 AI 提要求,copy / paste 代码,在venv验证运行,向 AI 反馈,总共用了3个 chats.(图中的只有一个 Chat, 删掉的另外两个: Python 库安…

海外云手机实现高效的海外社交媒体营销

随着全球化的深入发展,越来越多的中国企业走向国际市场,尤其是B2B外贸企业,海外社交媒体营销已成为其扩大市场的重要手段。在复杂多变的海外市场环境中,如何有效提高营销效率并降低运营风险,成为了众多企业的首要任务。…

计算机网络(十二) —— 高级IO

#1024程序员节 | 征文# 目录 一,预备 1.1 重新理解IO 1.2 五种IO模型 1.3 非阻塞IO 二,select 2.1 关于select 2.2 select接口参数解释 2.3 timeval结构体和fd_set类型 2.4 socket就绪条件 2.5 select基本工作流程 2.6 简单select的服务器代…

【mysql进阶】4-8 临时表空间

临时表空间 - Temporary Tablespaces 1 什么是临时表? ✅ 解答问题 临时表存储的是临时数据,不能永久的存储数据,⼀般在复杂的查询或计算过程中⽤来存储过渡的中间结果,MySQL在执⾏查询与计算的过程中会⾃动⽣成临时表&#xff0c…

C++ 抛异常

目录 一.抛异常与运行崩溃的区别 1.运行崩溃 2.抛异常 二.抛异常机制存在的意义 1.清晰的处理错误 2.结构化的错误管理 3.跨函数传递错误信息 4.异常对象多态性 三.抛异常的使用方法 1.抛出异常 (throw) 2.捕获异常 (catch) 3.标准异常类 四.抛异常的处理机制 1.抛…

2024“源鲁杯“高校网络安全技能大赛-Misc-WP

Round 1 hide_png 题目给了一张图片,flag就在图片上,不过不太明显,写个python脚本处理一下 from PIL import Image ​ # 打开图像并转换为RGB模式 img Image.open("./attachments.png").convert("RGB") ​ # 获取图像…

rabbitmq 使用注意事项

1,注意开启的端口号,一共四个端口号,1883是mqtt连接的端口号,如果没开,是连接不上的需要手动起mqtt插件。 //开始mqtt插件服务 rabbitmq-plugins enable rabbitmq_mqtt 2,15672端口是http网页登录的管理后…