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

Linux:程序地址空间/虚拟地址等相关概念理解

文章目录

  • 程序地址空间
  • 虚拟地址和物理地址
    • 地址的转换
    • 地址空间是什么?

程序地址空间

CC++程序中,一直有一个观点是,程序中的各个变量等都会有一定的地址空间,因此才会有诸如取地址,通过地址访问等操作,那么在前面的学习中,基本有下面的概念

在这里插入图片描述

这是学C语言的时候就已经知晓的内容,那么现在抛出下面的几个疑问:这些数据和所谓的地址是内存中的地址吗?内存中的地址存储排列形式如此整齐吗?不会造成内存浪费吗?

下面做一个小实验:

#include <stdio.h>
#include <unistd.h>int g_val = 100;
int main()
{pid_t id = fork();if(id == 0){//childint cnt = 5;while(1){printf("child, Pid: %d, Ppid: %d, g_val: %d, &g_val=%p\n", getpid(), getppid(), g_val, &g_val);sleep(1);if(cnt == 0){g_val=200;printf("child change g_val: 100->200\n");}cnt--;}}else{//fatherwhile(1){printf("father, Pid: %d, Ppid: %d, g_val: %d, &g_val=%p\n", getpid(), getppid(), g_val, &g_val);sleep(1);}}sleep(100);return 0;
}

实验结果如下:

child, Pid: 6781, Ppid: 6780, g_val: 100, &g_val=0x60105c
father, Pid: 6780, Ppid: 30413, g_val: 100, &g_val=0x60105c
child change g_val: 100->200
child, Pid: 6781, Ppid: 6780, g_val: 200, &g_val=0x60105c
father, Pid: 6780, Ppid: 30413, g_val: 100, &g_val=0x60105c

这是一个很神奇的现象,父进程和子进程的g_val选项的地址是一样的,但是读取出来的值却不一样,这是为什么呢?

说明这里的地址,并不是物理地址,而是虚拟地址,也叫做线性地址

虚拟地址和物理地址

下面就来研究的是,虚拟地址和物理地址之间是如何进行转换的

地址的转换

由前面的内容知道,进程是由进程的代码和数据以及内核数据结构组成的,那么当一个进程生成的时候会创建其对应的PCB用来管理进程中的数据,而在进程中的数据会根据具体的类型而放入不同的地址空间中,例如栈区,堆区,代码区等等…

而实际上,这个区域只是一个虚拟的地址,由于一些原因(后续补充),存在一个叫做页表的映射关系,将虚拟地址和物理地址进行一一映射,具体的表现如下所示:

在这里插入图片描述
上图即展示了页表的映射关系的具体含义,对于前面图片中的内容只是一个虚拟地址,打印出来的信息也并非实际的物理地址,而真正的物理地址则是通过页表进行一个一一映射的关系,通过这个一一映射就能够找到物理地址,这个物理地址才是真正存储信息的地方

那对于子进程来说是如何解释的?

由前面的理论基础可以得出这样的一个结论,当使用fork创建子进程的时候,为子进程创建自己的PCB,对于代码和数据,如果发生了变化就使用写时拷贝完成一份拷贝,这样可以保证进程的互不干扰独立性,因此对于上面的场景,当对于创建子进程的时候,本质上就是直接复制了一份上面图片中的内容,并将这个task_struct变成子进程:

下图中所示的页表是一部分,实际上的页表还有其他的组成部分

在这里插入图片描述
而当子进程或者父进程要发生数据改变的时候,就会发生写时拷贝,具体的产生过程如下:

在这里插入图片描述

这样,就解释清楚了写时拷贝的含义,写时拷贝是发生在物理内存中的拷贝过程,整个过程是由操作系统来完成的,保证了进程之间的独立性

地址空间是什么?

简单来说,地址空间就是它:

在这里插入图片描述
每一个进程都会有一个这样的地址空间,而对于地址空间是需要进行管理的,那么如何对地址空间进行管理?答案是先描述再组织,因此,如何对地址空间进行描述?

地址空间最终一定是一个内核的数据结构对象,简单来说就是一个内核的结构体,正如task_struct一样,在Linux内核中有一个名字,叫做mm_struct,而这个数据是如何进行管理的?答案很明显,也是在内核数据结构中进行的管理

Linux内核源码中,来查看这个结构体的存在性

在这里插入图片描述

转到关于它的定义,观看它内部的定义实现方式:

在这里插入图片描述
对于mm_struct来说,它通过定义了各个区域的起止位置来进行管理数据

为什么要有地址空间呢?

先说结论:

  1. 让进程以统一的视角看待内存,任意一个进程,都可以通过地址空间和页表,将杂乱无序的内存数据变成有序的空间,也就是说这是一个变无序为有序的过程
  2. 存在虚拟地址空间,可以有效的进行进程访问内存的安全检查
  3. 将进程管理和内存管理进行耦合
  4. 通过页表,可以让进程映射到不同的物理内存中,从而实现进程的独立性

下面对于上面的结论进行一一的解释:

1. 变无序为有序的过程

这个过程是很好理解的,由于页表的存在,因此具体的实际内存中的数据不必排放到一块,而是可以进行不同位置的存储,但是在管理的角度来看,通过虚拟地址来进行管理是相当方便的,每一个地方都被分门别类的具体一一列举了出来,这样不仅便于管理,同时也可以最大化的利用内存中的空间

2. 访问内存的安全检查

讲到这点,就必须对页表进行进一步的补充说明了,实际上页表中存储的不仅仅有虚拟地址和物理地址,还有其他很多的信息,例如这里的访问权限字段

在这里插入图片描述
那么首先是解释访问权限字段存在的意义:可以有效避免进行修改,保护进程的数据等功能,例如下面的这个具体事例

#include <stdio.h>
//#include <unistd.h>int main()
{char* str = "hello linux";*str = 'H';return 0;
}

gcc的编译器下,这是可以通过编译的,原因是这里的一个常量字符串的起始地址交给了一个字符指针str,而对于str来说将它的指向内容改成H,这个本身是可以的,但是问题出现在,str指向的内容实际上是一个字符常量区,而这个区域内的数据是不可以被修改的,因此如果要进行修改的话是不被允许的,那么页表是如何进行保护的呢?

在执行程序的时候会引发段错误,这就是页表的功劳,当使用虚拟地址进行映射到物理地址的过程中,在进行页表的权限访问字段的时候会发现这个字段的访问权限是只读权限,但是现在要进行写入,很明显这是不被允许的行为,因此就会终止这种行为,因此页表中的权限访问字段就有这样的功能,可以进行访问内存的安全检查

3. 将进程管理和内存管理进行耦合

在解释这个结论前,还需要补充一下页表的内容,页表中还存在一列,它的意义是查看是否被分配和是否有内容

在这里插入图片描述
在实际中是采用一个01来表示是否有没有被分配和内容的,在实际进程管理控制过程中,虚拟地址首先会放到页表中,而当需要和内存地址进行交互的时候,就会通过这个分配和内容的内容表来进行判断,到底内存有没有分配具体的物理地址给这部分内容,如果没有就会进行分配等信息,也是方便于进程的管理

这样做,就把进程管理和内存管理这两个模块的耦合度大大降低,两个模块控制系统互不干扰,这样就实现了进程的独立性

相关文章:

Linux:程序地址空间/虚拟地址等相关概念理解

文章目录 程序地址空间虚拟地址和物理地址地址的转换地址空间是什么&#xff1f; 程序地址空间 在C和C程序中&#xff0c;一直有一个观点是&#xff0c;程序中的各个变量等都会有一定的地址空间&#xff0c;因此才会有诸如取地址&#xff0c;通过地址访问等操作&#xff0c;那…...

Python之爬虫

目录 HTTP请求HTTP响应获得页面响应伪装用户访问打包数据爬取豆瓣top250 HTTP请求 HTTP&#xff1a;HypertextTransferProtcol 超文本传输协议 1、请求行 POST/user/info?new_usertrue HTTP/1.1#资源了路径user/info 查询参数new_usertrue 协议版本HTTP/1.1 2、请求头 Ho…...

打造自己的前端组件库(奶妈版,超详细)

打造自己的前端组件库 demo是开源的&#xff0c;自己上npm 或者 github 上都能搜到 新建vue项目(sass js vue2) vue create yt-ui 修改文件目录(如下) 修改&#xff1a; 1.src 更名 examples; 2. src/components移动到项目最外层&#xff1b;3.vue.config.js更改入口文件 /…...

6.调制阶数相关

1、调制阶数与峰均比的关系 调制阶数&#xff08;modulation order&#xff09;对峰均比&#xff08;有一定的影响。 峰均比是用于衡量调制信号或波形在幅度上的动态范围的指标。它表示信号的最大峰值与平均功率之间的比值。较高的峰均比可能导致信号在传输或放大过程中出现过…...

Maven多模块管理(转载)

注意&#xff1a;父模块需设定打包方式为pom https://cloud.tencent.com/developer/article/1667275 dependencyManagement 统一管理子类依赖版本 在父类maven中加入&#xff0c;不会继承给子类&#xff0c;只能规定子类的依赖版本&#xff0c;子类加入dependence后无需写入 …...

运维学习CentOS 7进行Nightingale二进制部署

.因为Nightingale需要MySQL保存一些数据&#xff0c;所以可以参考《CentOS 7.6使用mysql-8.0.31-1.el7.x86_64.rpm-bundle.tar安装Mysql 8.0》部署MySQL。 https://github.com/ccfos/nightingale/releases是可以github上下载Nightingale二进制安装包。 https://n9e.github.io/…...

安装Docker

本安装教程参考Docker官方文档&#xff0c;地址如下&#xff1a;https://docs.docker.com/engine/install/centos/ 卸载旧版 首先如果系统中已经存在旧的Docker&#xff0c;则先卸载&#xff1a; yum remove docker \ docker-client \ docker-client-latest \ docker-common…...

【uniapp/uView】解决消息提示框悬浮在下拉框之上

需要实现这样的效果&#xff0c;即 toast 消息提示框在 popup 下拉框之上&#xff1a; 解决方法&#xff0c;把 <u-toast ref"uToast" /> 放在 u-popup 里面即可&#xff0c;这样就可以提升 toast 的优先级&#xff1a; <!-- 弹出下拉框 --><u-popu…...

有效管理token,充分发挥ChatGPT的能力

目录 给提供了 Token 的计算工具,来理解一下Token的计算方式,网址如下: 窗口如下: 实际消耗 Token 数量为 59个,换算之后为2.1-2.2的比例,即一个汉字消耗2.12.2个Token, 再测一下英文的Token消耗,包含空格在内,一共52个英文字母,消耗Token 13个,正好对应13个单词,…...

Python —— 验证码的处理执行JavaScript语句

1、验证码的处理 1、概述&绕过验证码的方案 很多的网站都在登录页面加入了识别文字&#xff0c;识别图片&#xff0c;拖动拼图的验证码方式来防止爬虫、恶意注册 等&#xff0c;如果是做自动化&#xff0c;需要绕过验证码才能进入下一步操作&#xff0c;那么有4种方案可以…...

MS12_020 3389远程溢出漏洞

1.search ms12_020 搜索ms12_020 2.use auxiliary/scanner/rdp/ms12_020_check 检查是否存在ms12_020漏洞 show options 查看所需参数 set RHOSTS x.x.x.x 设置目标IP地址 run 执行 检测出来有Ms12_020漏洞 3.use auxiliary/dos/windows/rdp/ms12_020_maxchannelids 选择…...

Pytorch ddp切换forward函数 验证ddp是否生效

DDP及其在pytorch中应用 ddp默认调用forward函数&#xff0c;有些模型无法使用forward函数&#xff0c;可以对模型包装一下。 class modelWraper(nn.Module):def __init__(self, model):super().__init__()self.model modeldef forward(self, *args, **kwargs):return self.…...

C++中按引用向函数传递参数

C中按引用向函数传递参数 在参数传递过程中&#xff0c;如果实参与引用参数不匹配&#xff0c;C将生成临时变量。当前&#xff0c;仅当参数为 const 引用时&#xff0c;C才允许这么做&#xff0c;但以前不 是这样。如果引用参数是 const&#xff0c;则编译器将在下面两种情况…...

【Asp.net】Asp.net core中IIS配置注意事项

1、应用地址池设为无托管代码 一、提示&#xff1a;关于IIS上运行ASP.NET Core 站点的“HTTP 500.19”错误 安装dotnet-hosting-3.1.2-win.exe ASP.NET Core 3.1 Runtime (v3.1.2)下载地址&#xff1a; https://download.visualstudio.microsoft.com/download/pr/dd119832-dc4…...

Redis实现附近商户

GEO数据结构的基本用法 GEO就是Geolocation的简写形式&#xff0c;代表地理坐标。Redis在3.2版本中加入了对GEO的支持&#xff0c;允许存储地理坐标信息&#xff0c;帮助我们根据经纬度来检索数据。常见的命令有&#xff1a; GEOADD&#xff1a;添加一个地理空间信息&#xf…...

【COMP305 LEC 3 LEC 4】

LEC 3 A basic abstract model for a biological neuron 1. Weights of connections Neuron gets fired if it has received from the presynaptic neurons 突触前神经元 a summary impulse 脉冲, which is above a certain threshold. Signal from a single synapse突触 ma…...

国密https访问

前言 现在的SSL的加密算法实际上主要是国际算法&#xff0c;包括JDK&#xff0c;Go等语言也仅支持国际算法加密&#xff08;毕竟是国外开源项目&#xff09;&#xff0c;hash。随着国密算法的普及&#xff0c;比如openssl就支持国密了&#xff0c;还要新版本的Linux内核也开始…...

31二叉树-递归遍历二叉树

目录 LeetCode之路——145. 二叉树的后序遍历 分析 LeetCode之路——94. 二叉树的中序遍历 分析 LeetCode之路——145. 二叉树的后序遍历 给你一棵二叉树的根节点 root &#xff0c;返回其节点值的 后序遍历 。 示例 1&#xff1a; 输入&#xff1a;root [1,null,2,3] 输出…...

【【萌新的FPGA学习之管脚设定xdc文件】】

萌新的FPGA学习之管脚设定xdc文件 xdc文件可以自己设置 也可以匹配 我们根据正点原子的流水灯管脚设定 主要讲述一下 各个英文设计是什么意思 Name&#xff1a;工程中顶层端口的名称。 Direction&#xff1a;说明管脚是输入还是输出。 Neg Diff Pair&#xff1a;负差分对&…...

tomcat---动静分离

访问静态和动态页面分开 实现动态的静态页面负载均衡 实验一 准备阶段&#xff1a;三台虚拟机 nginx代理服务器 &#xff1a;20.0.0.40 tomcat1 &#xff1a;20.0.0.50 tomcat2&#xff1a;20.0.0.51 配置关闭虚拟机防火墙和安全机制 systemctl stop firewalld setenf…...

深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法

深入浅出&#xff1a;JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中&#xff0c;随机数的生成看似简单&#xff0c;却隐藏着许多玄机。无论是生成密码、加密密钥&#xff0c;还是创建安全令牌&#xff0c;随机数的质量直接关系到系统的安全性。Jav…...

【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)

升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点&#xff0c;但无自动故障转移能力&#xff0c;Master宕机后需人工切换&#xff0c;期间消息可能无法读取。Slave仅存储数据&#xff0c;无法主动升级为Master响应请求&#xff…...

重启Eureka集群中的节点,对已经注册的服务有什么影响

先看答案&#xff0c;如果正确地操作&#xff0c;重启Eureka集群中的节点&#xff0c;对已经注册的服务影响非常小&#xff0c;甚至可以做到无感知。 但如果操作不当&#xff0c;可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...

九天毕昇深度学习平台 | 如何安装库?

pip install 库名 -i https://pypi.tuna.tsinghua.edu.cn/simple --user 举个例子&#xff1a; 报错 ModuleNotFoundError: No module named torch 那么我需要安装 torch pip install torch -i https://pypi.tuna.tsinghua.edu.cn/simple --user pip install 库名&#x…...

React---day11

14.4 react-redux第三方库 提供connect、thunk之类的函数 以获取一个banner数据为例子 store&#xff1a; 我们在使用异步的时候理应是要使用中间件的&#xff0c;但是configureStore 已经自动集成了 redux-thunk&#xff0c;注意action里面要返回函数 import { configureS…...

JAVA后端开发——多租户

数据隔离是多租户系统中的核心概念&#xff0c;确保一个租户&#xff08;在这个系统中可能是一个公司或一个独立的客户&#xff09;的数据对其他租户是不可见的。在 RuoYi 框架&#xff08;您当前项目所使用的基础框架&#xff09;中&#xff0c;这通常是通过在数据表中增加一个…...

MySQL 知识小结(一)

一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库&#xff0c;分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷&#xff0c;但是文件存放起来数据比较冗余&#xff0c;用二进制能够更好管理咱们M…...

WebRTC从入门到实践 - 零基础教程

WebRTC从入门到实践 - 零基础教程 目录 WebRTC简介 基础概念 工作原理 开发环境搭建 基础实践 三个实战案例 常见问题解答 1. WebRTC简介 1.1 什么是WebRTC&#xff1f; WebRTC&#xff08;Web Real-Time Communication&#xff09;是一个支持网页浏览器进行实时语音…...

从面试角度回答Android中ContentProvider启动原理

Android中ContentProvider原理的面试角度解析&#xff0c;分为​​已启动​​和​​未启动​​两种场景&#xff1a; 一、ContentProvider已启动的情况 1. ​​核心流程​​ ​​触发条件​​&#xff1a;当其他组件&#xff08;如Activity、Service&#xff09;通过ContentR…...

LOOI机器人的技术实现解析:从手势识别到边缘检测

LOOI机器人作为一款创新的AI硬件产品&#xff0c;通过将智能手机转变为具有情感交互能力的桌面机器人&#xff0c;展示了前沿AI技术与传统硬件设计的完美结合。作为AI与玩具领域的专家&#xff0c;我将全面解析LOOI的技术实现架构&#xff0c;特别是其手势识别、物体识别和环境…...