Linux——进程地址空间,写时拷贝,进程独立性

news/2024/7/7 20:09:02

Linux进程内存分布

验证地址空间排布


结论:堆区向地址增大的方向增长,栈区向地址减少的方向增长。局部变量通常保存在栈上,先定义的先入栈,地址是比较高的,后定义的则地址小。

static变量

作用域不变,生命周期改变,如何改变?
编译器会把静态变量放到全局区。静态变量和全局变量的存在同一块空间的,但是只有在函数内才可见。

进程地址空间

每一个进程被运行的时候,操作系统都会为其创建进程地址空间,也会建立各自的页表。虚拟地址空间是物理地址的映射。
如何管理地址空间?
先描述再组织。进程地址空间实际上也是内核中的一个数据结构,mm_struct。
虚拟地址和物理地址之间会有一个页表用于建立映射关系。

mm_struct和vm_area_struct

mm_struct是虚拟地址空间,vm_area_struct是用于划分区域的。
task_struct里有一个mm_struct指针指向虚拟地址空间结构体。
mm_struct里有一个vm_area_struct指针指向mmap,维护了虚拟地址空间的各个区域,来划分每一个区域(栈、堆、代码区)的起点与终点。

unsigned long total_vm, locked_vm, shared_vm, exec_vm;

unsigned long stack_vm, reserved_vm, def_flags, nr_ptes;

unsigned long start_code, end_code, start_data, end_data;

unsigned long start_brk, brk, start_stack;

unsigned long arg_start, arg_end, env_start, env_end;

标识每个区域的起始和终止地址范围。
这里的地址作为页表的K值来与物理地址建立映射。
页表是进程加载到程序的时候自动建立的。通过页表的K值找到实际物理内存里的数据。

程序是如何被加载变成进程的?

程序被编译后,还没被加载,此时程序内部有地址和区域吗?
有!链接就是把程序内部函数的地址和库中函数的地址关联起来。
编译后区域已经划分好了,变量放在对应的区域。除了堆区和栈区是加载到内存之后才有的。

进程本身中的代码也会有地址,但是这个地址是虚拟地址,在页表中作为K值,经过映射,加上偏移量,就能找到实际占用操作系统资源的地址。

比如程序中函数的代码的地址在程序中已经确定,为0x100,加载到内存后,这个地址加上了偏移量10000,放在了内存上的代码区。进程开始后,运行到这里,就要到物理内存中的0x10100中去找。编译后代码的位置已经确定,放到内存中又是一回事,因此要加上偏移量放到物理内存上。

fork的返回值


修改子进程val后父进程的val不变,同一地址的变量会有两个值?

很显然,在C/C++中的地址并不是内存物理上的地址,而是操作系统提供的虚拟地址,操作系统不允许直接读取物理内存。虚拟地址是一样的,但是物理地址是不一样的。

val是父进程的栈空间中的变量,fork函数return会被执行两次,return的本质就是通过寄存器赋值。当父子各自执行return,会发生写时拷贝。

写时拷贝

进程具有独立性,为了保证进程间数据独立,进程间不相互干扰,会有数据的写时拷贝,得到一张新的页表。在上面的程序中,变量的物理地址实际就不同了,因此数据也是不同的。

为什么要写时拷贝?

为什么不创建子进程的时候就写时拷贝?
在数据被修改的时候再深拷贝,而不是一开始就全部拷贝下来,因为可能数据都是只读的,可以节省空间。
最理想的是:只拷贝父进程中会被修改的数据,但是这是无法预测的,因此只能采用写时拷贝这种方式妥协。

代码会不会有写时拷贝?
如果涉及程序替换的时候就会。

为什么要有进程地址空间?

保证进程的独立性

有了自己的虚拟空间之后,就不会有任何系统级别的越界问题存在了。对某一地址空间进行操作之前需要先通过页表映射到物理内存,而页表只会映射属于各个进程自己的物理内存。

解耦了虚拟地址和物理地址

每个进程都认为拥有相同的空间范围,认为自己在独占内存,包括进程地址空间的构成和内部区域的划分顺序等都是相同的,编写程序的时候就只需关注虚拟地址,而无需关注数据在物理内存当中实际的存储位置。

进一步完善进程的独立性以及合理分配内存空间(当实际需要使用内存空间的时候再在内存进行开辟),并能将进程调度与内存管理进行解耦或分离。

比如Linux下向系统malloc申请空间时,系统不会立即真实分配,而只是修改vm_area中的起点和终点,因为怕用户占着不用浪费资源,而是在用户调用到的时候再立刻申请,建立页表映射关系。


http://lihuaxi.xjx100.cn/news/1274212.html

相关文章

Linux之tar安装

目录 Linux之tar安装 定义 工作过程 语法格式 参数及用法 使用源代码安装软件的优点 注意:源代码编译环境 操作流程 解包 —— tar 配置 —— ./configure 编译 —— make 安装 —— make install 案例 --- 安装Apache服务 1.获取安装包地址并下载 2…

word文档批量生成工具(附免费软件)(按Excel表格内容自动替换内容生成文档)

批量生成word文档是让人无比厌恶但有时又不得不做的事情。比如学校要给拟录取的学生发通知书,就可能需要批量生成一批只有“姓名”、“学院”和“专业”不同,其他内容都相同的word文档以供打印(事实上直接生成pdf是更好的选择,这个…

Windows10host文件修改方法

1、首先打开“此电脑”,定位到: C:\Windows\System32\drivers\etc 2、使用鼠标右键单击“hosts”,弹出来的菜单中选择“属性” 3、弹出“文件属性”窗口后单击“上方的”安全“栏”。 选中“ALL APPLICATON PACKAGES”后单击“编辑” 4、同…

“破解求职之谜:应届生如何应对职场场景挑战?

今天,我想与你分享一个关于应届生面试的故事。这是一个真实且令人深思的故事,也是我个人在求职过程中的一次经历,这也是对尚未面试者的警醒对已面试者的勉励。 在暑期还未开始之前,我充满着憧憬和期待地投递了许多简历&#xff0c…

【瑞萨RA_FSP】WiFi——ESP8266模块通讯

文章目录 一、Wifi模块简介二、ESP8266功能介绍1. 通用输入/输出接口(GPIO)2. 使用UART与WIFI通讯3. ESP8266工作模式介绍 三、AT指令四、实验:STA模式测试1. 文件结构2. 宏定义函数3. ESP8266-STA功能函数4. 中断回调函数5. hal_entry入口函…

【深度学习笔记】神经网络概述

本专栏是网易云课堂人工智能课程《神经网络与深度学习》的学习笔记,视频由网易云课堂与 deeplearning.ai 联合出品,主讲人是吴恩达 Andrew Ng 教授。刚兴趣的网友可以观看网易云课堂的视频进行深入学习,视频的链接如下:https://mo…

【MySQL】表的内外连接

目录 一、内连接(表1 inner join 表2 on) 1、显示SMITH的名字和部门名称 二、外连接 1、左外连接(表名1 left join 表名2 on) 1.1查询所有学生的成绩,如果这个学生没有成绩,也要将学生的个人信息显示出…

小程序布局中相对定位的用法

小程序中一般为了有一定的设计效果,会将下边组件的内容提升一点到上边去,比如我们的电商展示模板里,会将商品列表覆盖一点到背景图,效果如下: 这种要如何搭建呢?就是利用到了CSS相对定位的原理 搭建组件 …