【Linux】地址空间

本片博客将重点回答三个问题
什么是地址空间?
地址空间是如何设计的?
为什么要有地址空间?
程序地址空间排布图
在32位下,一个进程的地址空间,取值范围是0x0000 0000~ 0xFFFF FFFF
在这里插入图片描述
回答三个问题之前我们先来证明地址空间排布是按如图所布局的
各个区空间地址验证代码

#include <unistd.h>
#include <stdio.h>                                                                                           
#include <stdlib.h>

int g_unval; // 未初始化数据
int g_val = 100; // 初始化数据,一般指全局初始化数据
int main(int argc, char* argv[], char* env[]) // 命令行参数,环境变量
{
	// 代码地址打印                          
    printf("code addr: %p\n", main); 
    printf("init global addr: %p\n", &g_val);
    printf("uninit global addr: %p\n", &g_unval);
    
    // 堆区,指针变量本质是变量,也要开辟空间,不过放的内容是地址
    char *heap_mem = (char*)malloc(10);
    printf("heap addr: %p\n", heap_mem);
    
    // 栈区,函数内定义的变量都是在栈上开辟空间
    printf("stack addr: %p\n", &heap_mem); 
     
    int i = 0;
    for (i = 0; i < argc; i++)
    {	
    	// 命令行参数地址	
        printf("argv[%d]: %p\n", i, argv[i]);
    }
    int j = 0;
    for (j  = 0; env[j]; j++)
    {
        printf("env[%d]: %p\n", j, env[j]);
    }
    return 0;
 }

运行结果
在这里插入图片描述
堆、栈之间的两个箭头表示
栈向地址减小的方向增长
堆向地址增大的方向增长
在这里插入图片描述
证明方法也很简单
在这里插入图片描述
运行结果也证明确实是这样
我们会发现堆区之间差了20字节
我们平时申请空间,系统会多给你一些空间
多出的空间用来记录你堆的属性信息
所以平时我们free空间,只要传起始地址
剩下的系统知道要free多长的空间
在这里插入图片描述

我们在系统部分要记的两个口诀
1、先描述在组织
2、堆、栈相对而生

static 修饰局部变量,本质就是将该变量开辟在全局区域

所有的字面常量将来都是要映编码进代码的
在正文代码上其实有一小段是字符常量区
在这里插入图片描述

什么是地址空间以及是如何设计的

我们平时打印各种地址其实就是进程打印,程序运行之后打印的

在解释什么是地址空间之前,我们先来讲一个故事

有一个富豪,他有5亿元家产
他有3个私生子,彼此并不知道对方存在
3个私生子分别叫张三、李四、王五
富豪为了鼓励3个儿子
对张三说你好好念书将来5亿就是你的了
对另外两个儿子也说了同样的话

因为不知道彼此存在
对于这三个儿子,他们都认为是5亿继承人
富豪给他们每一个儿子画了一个大饼

有一天,张三对他爸说要1千买学习资料
李四说我成年了想买一辆两百万的跑车
王五说我创业需要50万
富豪都给了他们需要的钱
只要他们要钱富豪都会给
有一天张三说要1亿,富豪说要这么多干嘛
拒绝了张三,即使被拒绝了张三依旧认为自己是5亿的继承人
我们站在上帝视角知道即使富豪过世了
这三个儿子不可能都拥有5亿
他们每个儿子可以断断续续的要钱
但永远要不到5亿,却依然坚信自己以后能拥有这5亿

对应关系
富豪 ---- 操作系统
儿子 ---- 进程
富豪画的饼 ---- 地址空间

在内存中的地址空间本质是一种数据结构
将来要和一个特定的进程关联起来

以前直接访问物理内存,如果有野指针的问题
可能直接访问到其他进程
内存本身是随时可以被读写
所以在老式的程序里面野指针是会直接改了其他进程的东西
结论:直接使用物理内存不安全

现代计算机的解决方式

每个进程有自己的PCB
操作系统给每个进程一个虚拟的地址空间
通过映射机制映射到物理内存
我们可能会有疑问,最终还是会访问物理内存
万一虚拟地址是一个非法地址呢
其实映射机制有一个检查机制,万一是非法地址
可以不让你映射

在这里插入图片描述

虚拟地址空间究竟是什么?

每个进程都要有地址空间
就好比操作系统要给每个进程画个饼
操作系统要给每个饼做管理
在内存中的地址空间本质是一种内核数据结构
它里面至少有各个区域的划分
在这里插入图片描述
我们把如图结构称为地址空间

区域空间并不是死的,会有一定的变化
所谓的范围变化,本质是对start 或end 标记值 + - 特定的范围即可
在这里插入图片描述
所以一个地址为什么有两个值
到这里就可以回答这个问题了

刚开始创建时只有父进程
然后创建子进程,子进程会继承父进程的属性
所以子进程的页表、地址空间和父进程一样
当子进程尝试修改变量值时
因为要保证进程的独立性
操作系统会重新为子进程,开辟一份物理内存
并修改子进程页表的映射关系
但是虚拟地址并不受影响,还是一样的地址
但映射到物理内存的不同区域
看到的值便不一样
这种策略就叫作写时拷贝

在这里插入图片描述

为什么要存在地址空间

  1. 保护物理内存
    凡是非法的访问或者映射,
    os都会识别到,并且终止你这个进程
    因为地址空间和页表是os创建并维护的
    也就意味着凡是想使用地址空间和页表
    进行映射,也一定要在OS的监管下进行访问
  2. OS耦合度更低
    因为有地址空间的存在
    因为有页表映射的存在
    我们的物理内存就可以
    对未来的数据进行任意位置的加载
    物理内存的分配就可以和
    进程的管理互不关联
    从而使内存管理模块和进程管理模块
    完成解耦合

我们在C、C++语言上new、malloc空间时
本质是在虚拟地址空间申请的
因为有地址空间的存在,所以上层申请空间
物理内存可以甚至一个字节都不给你
当你真正访问物理地址时,才执行
内存相关算法,帮你申请内存,构建
页表映射关系,这样空间使用率为100%
以此提高整机效率

  1. 保证进程的独立性
    因为有地址空间的存在,每一个进程
    都认为自己拥有4GB的空间(32)
    并且各个区域是有序的,进而
    可以通过页表映射到不同的区域
    来实现进程的独立性,每一个进程
    不知道,也不需要知道其他进程的存在

重新理解什么是挂起?

加载的本质就是创建进程,但并不是
非得把所有程序的代码和数据加载到
内存中,并创建内核数据结构建立映射关系
在极端情况下,只有内核结构被创建
此时就叫新建状态

理论上,可以实现对程序的分批加载
既然可以分批加载,自然可以分批换出
一个进程短时间不会被执行,比如阻塞
而使进程的数据和代码被换出就叫挂起

页表不仅仅映射物理内存
磁盘位置也可以映射
所以当代码挂起时,不用把数据
刷新到磁盘里。只要把空间直接释放掉,
在页表重新填上磁盘当中代码和数据的
位置,就可以完成一次基本的挂起

扩展知识

在vim中注释
Ctrl + v 进入视图模式(V-BLOCK)
hjkl 选中需要注释代码
输入大写的i,左下角出现INSERT
输入 // ,再按esc 自动注释选中的代码
取消注释还是上面的操作
选中需要注释的代码,按d删除

✨✨✨✨✨
本篇博客完,感谢阅读🌹🌹🌹
如有错误之处可评论指出,博主会耐心听取每条意见

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

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

相关文章

react中使用react-konva实现画板框选内容

文章目录 一、前言1.1、API文档1.2、Github仓库 二、图形2.1、拖拽draggable2.2、图片Image2.3、变形Transformer 三、实现3.1、依赖3.2、源码3.2.1、KonvaContainer组件3.2.2、use-key-press文件 3.3、效果图 四、最后 一、前言 本文用到的react-konva是基于react封装的图形绘…

Scrum

Scrum是一个用于开发和维持复杂产品的框架&#xff0c;是一个增量的、迭代的开发过程。在这个框架中&#xff0c;整个开发过程由若干个短的迭代周期组成&#xff0c;一个短的迭代周期称为一个Sprint&#xff0c;每个Sprint的建议长度是2到4周(互联网产品研发可以使用1周的Sprin…

序列的Z变换(信号的频域分析)

1. 关于Z变换 2. 等比级数求和 3. 特殊序列的Z变换 4. 因果序列/系统收敛域的特点 5. 例题

力扣 4. 寻找两个正序数组的中位数

题目 给定两个大小分别为 m 和 n 的正序&#xff08;从小到大&#xff09;数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。 算法的时间复杂度应该为 O(log (mn)) 。 My class Solution {public double findMedianSortedArrays(int[] nums1, int[] nums2) {i…

LLM之Agent(五)| AgentTuning:清华大学与智谱AI提出AgentTuning提高大语言模型Agent能力

​论文地址&#xff1a;https://arxiv.org/pdf/2310.12823.pdf Github地址&#xff1a;https://github.com/THUDM/AgentTuning 在ChatGPT带来了大模型的蓬勃发展&#xff0c;开源LLM层出不穷&#xff0c;虽然这些开源的LLM在各自任务中表现出色&#xff0c;但是在真实环境下作…

按天批量创建间隔分区表(DM8:达梦数据库)

DM8:达梦数据库-按天批量创建间隔分区表 环境介绍1 生成按天批量创建间隔分区表的日志2 整合后的日志信息3 创建成功4 达梦数据库学习使用列表 环境介绍 由于未知原因限制,按天批量创建间隔分区表最大是103行记录,需要反复执行几次,提取日志,整合后最终创建成功; 1 生成按天批…

AGILE-SCRUM

一个复杂的汽车ECU开发。当时开发队伍遍布全球7个国家&#xff0c;10多个地区&#xff0c;需要同时为多款车型定制不同的软件&#xff0c;头疼的地方是&#xff1a; 涉及到多方人员协调&#xff0c;多模块集成和管理不同软件团队使用的设计工具、验证工具&#xff0c;数据、工…

python安装与工具PyCharm

摘要&#xff1a; 周末闲来无事学习一下python&#xff01;不是你菜鸡&#xff0c;只不过是对手太强了&#xff01;所以你要不断努力&#xff0c;去追求更高的未来&#xff01;下面先了解python与环境的安装与工具的配置&#xff01; python安装&#xff1a; 官网 进入官网下载…

【Linux】输出缓冲区和fflush刷新缓冲区

目录 一、输出缓冲区 1.1 输出缓冲区的使用 1.2 缓冲区的刷新 1.3 输出缓冲区的作用 二、回车换行 一、输出缓冲区 C/C语言&#xff0c;当调用输出函数&#xff08;如printf()、puts()、fwrite()等&#xff09;时&#xff0c;会给我们提供默认的缓冲区。这些数据先存…

Python绘制多分类ROC曲线

目录 1 数据集介绍 1.1 数据集简介 1.2 数据预处理 2随机森林分类 2.1 数据加载 2.2 参数寻优 2.3 模型训练与评估 3 绘制十分类ROC曲线 第一步&#xff0c;计算每个分类的预测结果概率 第二步&#xff0c;画图数据准备 第三步&#xff0c;绘制十分类ROC曲线 1 数据集…

C++学习笔记之五(String类)

C 前言getlinelength, sizec_strappend, inserterasefindsubstrisspace, isdigit 前言 C是兼容C语言的&#xff0c;所以C的字符串自然继承C语言的一切字符串&#xff0c;但它也衍生出属于自己的字符串类&#xff0c;即String类。String更像是一个容器&#xff0c;但它与容器还…

uniapp如何制作一个收缩通讯录(布局篇)

html&#xff1a; <view class"search"><view class"search_padding"><u-search change"search" placeholder"请输入成员名称" v-model"keyword"></u-search></view></view> <view…

【面试经典150 | 二叉树】从中序与后序遍历序列构造二叉树

文章目录 写在前面Tag题目来源题目解读解题思路方法一&#xff1a;递归 写在最后 写在前面 本专栏专注于分析与讲解【面试经典150】算法&#xff0c;两到三天更新一篇文章&#xff0c;欢迎催更…… 专栏内容以分析题目为主&#xff0c;并附带一些对于本题涉及到的数据结构等内容…

2020年第九届数学建模国际赛小美赛A题自由泳解题全过程文档及程序

2020年第九届数学建模国际赛小美赛 A题 自由泳 原题再现&#xff1a; 在所有常见的游泳泳姿中&#xff0c;哪一种最快&#xff1f;哪个冲程推力最大&#xff1f;在自由泳项目中&#xff0c;游泳者可以选择他们的泳姿&#xff0c;他们通常选择前面的爬行。然而&#xff0c;游泳…

中文分词演进(查词典,hmm标注,无监督统计)新词发现

查词典和字标注 目前中文分词主要有两种思路&#xff1a;查词典和字标注。 首先&#xff0c;查词典的方法有&#xff1a;机械的最大匹配法、最少词数法&#xff0c;以及基于有向无环图的最大概率组合&#xff0c;还有基于语言模型的最大概率组合&#xff0c;等等。 查词典的方法…

esxi全称“VMware ESXi

esxi全称“VMware ESXi”&#xff0c;是可直接安装在物理服务器上的强大的裸机管理系统&#xff0c;是一款虚拟软件&#xff1b;ESXi本身可以看做一个操作系统&#xff0c;采用Linux内核&#xff0c;安装方式为裸金属方式&#xff0c;可直接安装在物理服务器上&#xff0c;不需…

TCP传输数据的确认机制

实际的TCP收发数据的过程是双向的。 TCP采用这样的方式确认对方是否收到了数据&#xff0c;在得到对方确认之前&#xff0c;发送过的包都会保存在发送缓冲区中。如果对方没有返回某些包对应的ACK号&#xff0c;那么就重新发送这些包。 这一机制非常强大。通过这一机制&#xf…

Redis如何做内存优化?

Redis如何做内存优化&#xff1f; 1、缩短键值的长度 缩短值的长度才是关键&#xff0c;如果值是一个大的业务对象&#xff0c;可以将对象序列化成二进制数组&#xff1b; 首先应该在业务上进行精简&#xff0c;去掉不必要的属性&#xff0c;避免存储一些没用的数据&#xff1…

博途PLC SCL间接寻址编程应用

这篇博客里我们将要学习Pointer和Any指针&#xff0c;PEEK和POKE指令&#xff0c;当然我们还可以数组类型数据实现数组指针寻址&#xff0c;具体应用介绍请参考下面文章链接&#xff1a; https://rxxw-control.blog.csdn.net/article/details/134761364https://rxxw-control.b…

15.Java程序设计-基于SSM框架的微信小程序校园求职系统的设计与实现

摘要&#xff1a; 本研究旨在设计并实现一款基于SSM框架的微信小程序校园求职系统&#xff0c;以提升校园求职流程的效率和便捷性。通过整合微信小程序平台和SSM框架的优势&#xff0c;本系统涵盖了用户管理、职位发布与搜索、简历管理、消息通知等多个功能模块&#xff0c;为…