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来表示是否有没有被分配和内容的,在实际进程管理控制过程中,虚拟地址首先会放到页表中,而当需要和内存地址进行交互的时候,就会通过这个分配和内容的内容表来进行判断,到底内存有没有分配具体的物理地址给这部分内容,如果没有就会进行分配等信息,也是方便于进程的管理

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

线性代数-Python-02:矩阵的基本运算 - 手写Matrix及numpy中的用法

文章目录 一、代码仓库二、矩阵的基本运算2.1 矩阵的加法2.2 矩阵的数量乘法2.3 矩阵和向量的乘法2.4 矩阵和矩阵的乘法2.5 矩阵的转置 三、手写Matrix代码Matrix.pymain_matrix.pymain_numpy_matrix.py 一、代码仓库 https://github.com/Chufeng-Jiang/Python-Linear-Algebra-…

Golang笔记

01 = 和 := 的区别? 前者是赋值变量,后者是定义变量 02 指针的作用 指针指向变量的地址,在64位机器上占8个字节 【1 字节(Byte)= 8 位(bit) 1 千字节(KB,Kilobyte)= 1,024 字节(2^10 字节)】 作用 取址然后取值swap函数 交换变量的值指针接收器来改变结构体里面…

Python机器学习入门指南

前言 机器学习 作为人工智能领域的核心组成&#xff0c;是计算机程序学习数据经验以优化自身算法&#xff0c;并产生相应的“智能化的”建议与决策的过程。 一个经典的机器学习的定义是&#xff1a; A computer program is said to learn from experience E with respect to …

打造属于自己的vue图标库

hfex-icon图标库 Install npm i -D hfex-icon主要提供2种使用方式 方式一 通过svg图标资源&#xff0c;借助unplugin-icons库将svg图标文件生成vue组件&#xff0c;然后通过vue组件的引入方式在vue中使用 unplugin-icons 兼容vue2和vue3 在vue.config.js的plugins中配置…

【C语言】进阶——程序编译

目录 一&#xff1a;&#x1f512;程序环境 程序的翻译环境和执行环境 &#x1f4a1;1.1翻译环境 预编译阶段&#xff1a; 编译阶段&#xff1a; 汇编阶段&#xff1a; 链接阶段&#xff1a; &#x1f4a1;1.2运行环境 二&#xff1a;&#x1f512;预处理详解 &…

文件夹图片相似图片检测并删除相似图片

项目开源地址 pip install imagededupgit clone https://github.com/idealo/imagededup.git cd imagededup pip install "cython>0.29" python setup.py installQuick Start from imagededup.methods import PHash phasher PHash()# Generate encodings for all…

分类预测 | Matlab实现WOA-BiLSTM鲸鱼算法优化双向长短期记忆神经网络的数据多输入分类预测

分类预测 | Matlab实现WOA-BiLSTM鲸鱼算法优化双向长短期记忆神经网络的数据多输入分类预测 目录 分类预测 | Matlab实现WOA-BiLSTM鲸鱼算法优化双向长短期记忆神经网络的数据多输入分类预测分类效果基本描述程序设计参考资料 分类效果 基本描述 1.Matlab实现WOA-BiLSTM鲸鱼算法…

oracle-AWR报告生成方法

AWR报告生成方法 1. 以oracle用户登陆服务器 2. 进入到要保存awr报告的目录 3. 以sysdba身份连接数据库 sqlplus / as sysdba4. 执行生成AWR报告命令 ?/rdbms/admin/awrrpt.sql5. 选择AWR报告的文件格式 6. 选择生成多少天的AWR报告 7. 选择报告的快照起始和结束ID 8. 输入生…

MongoDB深度学习

MongoDB的简介 什么是MongoDB? MongoDB是一个基于分布式文件存储的数据库&#xff0c;由C语言编写。MongoDB是一个介于关系数据库和非关系数据库之间的产品&#xff0c;是非关系数据库当中功能最丰富&#xff0c;最像关系数据库的&#xff0c;它支持的数据结构非常松散&…

面试算法31:最近最少使用缓存

题目 请设计实现一个最近最少使用&#xff08;Least Recently Used&#xff0c;LRU&#xff09;缓存&#xff0c;要求如下两个操作的时间复杂度都是O&#xff08;1&#xff09;。 get&#xff08;key&#xff09;&#xff1a;如果缓存中存在键key&#xff0c;则返回它对应的值…

【二维差分】ICPC南京 A

https://codeforces.com/gym/104128/problem/A 题意 思路 二维差分经典模型 考虑如果没有洞那么经历操作之后会剩下什么样子的袋鼠。发现上下左右移动可以看成是边界在移动&#xff0c;边界一直保持一个原初的矩形形状&#xff0c;而且上下移动和左右移动没有任何关系。一旦…

【LeetCode刷题(数据结构与算法)】:将二叉搜索树转化为排序的双向链表

将一个 二叉搜索树 就地转化为一个 已排序的双向循环链表 对于双向循环列表&#xff0c;你可以将左右孩子指针作为双向循环链表的前驱和后继指针&#xff0c;第一个节点的前驱是最后一个节点&#xff0c;最后一个节点的后继是第一个节点 特别地&#xff0c;我们希望可以 就地 完…

Elasticsearch 8.9 Master节点处理请求源码

大家看可以看ElasticSearch源码&#xff1a;Rest请求与Master节点处理流程&#xff08;1&#xff09; 这个图非常好&#xff0c;下午的讲解代码在各个类和方法之间流转&#xff0c;都体现这个图上 一、Master节点处理请求的逻辑1、节点(数据节点)要和主节点进行通讯&#xff0…

【数据结构】线性表(四)双向链表的各种操作(插入、删除、查找、修改、遍历打印)

目录 线性表的定义及其基本操作&#xff08;顺序表插入、删除、查找、修改&#xff09; 四、线性表的链接存储结构 1. 单链表 2. 循环链表 3. 双向链表 a. 双向链表节点结构 b. 创建一个新的节点 c. 在链表末尾插入节点 d. 在指定位置插入节点 e. 删除指定位置的节点…

Juniper防火墙SSG-140 session 过高问题

1.SSG-140性能参数 2.问题截图 3.解决方法 &#xff08;1&#xff09;通过telnet 或 consol的方法登录到防火墙&#xff1b; &#xff08;2&#xff09;使用get session 查看总的session会话数&#xff0c;如果大于300 一般属于不正常情况 &#xff08;3&#xff09;使用get…

H5随机短视频滑动版带打赏源码,可封装APP软件或嵌入式观看

H5随机短视频滑动版带打赏源码&#xff0c;可封装APP软件或嵌入式观看&#xff0c;网站引流必备源码&#xff01; 数据来源抖音和快手官方短视频链接&#xff0c;无任何违规内容&#xff01;可自行添加广告等等&#xff01; 手机端完美支持滑动屏幕观看&#xff08;向上或向右…

思维模型 上瘾模型(hook model)

本系列文章 主要是 分享 思维模型&#xff0c;涉及各个领域&#xff0c;重在提升认知。你到底是怎么上瘾&#xff08;游戏/抖音&#xff09;的&#xff1f;我们该如何“积极的上瘾”&#xff1f;让我们来一切揭晓这背后的秘密。 1 上瘾模型的应用 1.1上瘾模型的积极应用 1 学…

RT-Thread学习笔记(三):线程管理

线程管理 线程管理相关概念什么是时间片轮转调度器锁线程运行机制线程的五种状态 动态和静态创建线程区别动态和静态创建线程优缺点RT-Thread动态线程管理函数动态创建线程动态删除线程 RT-Thread静态线程管理函数静态创建线程 线程其他操作线程启动线程延时获得当前执行的线程…

四、基本组件

1. Designer设计师 Designer程序是Qt官方推出的专为设计人员使用的UI设计工具&#xff0c;程序员可以使用此工具大幅降低UI设计的代码量。 Designer设计文件的格式是.ui&#xff0c;需要配合同名的头文件与源文件使用。.ui文件通常被称为界面文件&#xff0c;其内部是xml语法的…

微机原理:汇编语言语句类型与格式

文章目录 壹、语句类型1、语句分类2、常用伪代码和运算符2.1数据定义伪指令2.1.1字节定义伪指令DB&#xff08;8位&#xff09;2.1.2字定义伪指令DW&#xff08;16位&#xff09;2.1.3双字节伪指令DD2.1.4 多字节定义DF/DQ/DT&#xff08;了解&#xff09; 2.2 常用运算符2.2.1…