Linux修炼之路之进程地址空间

news2024/9/23 7:30:03

目录

 一:程序地址空间

二:相关细节知识

接下来的日子会顺顺利利,万事胜意,生活明朗-----------林辞忧

 一:程序地址空间

1.在学习c/c++时,经常会听到堆区,栈区,代码段,常量区等对于空间中内存的划分

接下来将通过在Linux运行代码的结果来再次认识地址空间的划分

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int g_val_1;
int g_val_2 = 100;

int main(int argc, char *argv[], char *env[])
{
    printf("code addr: %p\n", main);
    const char *str = "hello bit";
    printf("read only string addr: %p\n", str);
    printf("init global value addr: %p\n", &g_val_2);
    printf("uninit global value addr: %p\n", &g_val_1);
    char *mem = (char*)malloc(100);
    char *mem1 = (char*)malloc(100);
    char *mem2 = (char*)malloc(100);
    printf("heap addr: %p\n", mem);
    printf("heap addr: %p\n", mem1);
    printf("heap addr: %p\n", mem2);
    printf("stack addr: %p\n", &str);
    printf("stack addr: %p\n", &mem);
    static int a = 0;
    int b;
    int c;
    printf("a = stack addr: %p\n", &a);
    printf("stack addr: %p\n", &b);
    printf("stack addr: %p\n", &c);
    int i = 0;
    for(; argv[i]; i++)
        printf("argv[%d]: %p\n", i, argv[i]);

    for(i=0; env[i]; i++)
        printf("env[%d]: %p\n", i, env[i]);

 

2.static修饰的局部变量,在编译时会被编译到全局数据区

3. 当执行这段代码之后

 

会发现这里同一个地址保存了两个不同的值,因此这里的地址不是物理地址,因为每个物理地址只能保存一个值,这里的地址则是虚拟地址(线性地址) ,对于平时所用的指针的地址等都是虚拟地址

4.当父进程创建出来后,系统为了让该进程更好的运行,除了创建内核数据结构PCB之外,操作系统还要为进程创建进程地址空间(内核为进程创建的结构体对象),因此每个进程在创建时,操作系统都要为进程创建对应的地址空间,并且对应的PCB中是有指针指向地址空间的

5.当系统要为该变量 在内存当中开辟一段空间时,在对应的物理内存上也会开辟一段空间,并且将虚拟地址和物理地址对应的存放在页表当中,因此每个进程都有自己的代码和数据,对应的进程就可以通过虚拟地址映射出物理地址,找到自己的代码和数据

6.当进程在访问虚拟内存时,操作系统会自动根据页表将虚拟地址转化为物理地址,这样就可以访问到物理内存中的内容

 7.刚开始时,父进程有自己的代码和数据,在创建子进程时,子进程会以父进程为模板来初始化自己内部的结构体对象的各种值,当然也有自己的一部分以写时拷贝的方式私有的数据,把父进程的地址空间和页表也会拷贝一份,这样刚开始时,父子进程共用一张页表,也因此指向的空间相同,父子进程共享代码和数据(保存在物理内存中),但因为进程独立性,子进程也有属于自己的页表和进城地址空间

8.当子进程对虚拟地址中内容进行修改时,在系统层面上识别到往虚拟地址中写入,由页表查询到对应被修改内容的物理地址,若这个变量是父子共享的话,操作系统会在写入之前在物理内存中重新划分一块空间,将历史值修改过来,再更新页表中新空间的物理地址,使其指向新空间,将父子共享的数据在物理内存上分开了。即子进程修改了数据,要发生写时拷贝,再重新建立映射关系,在父子访问时,就会分别映射到不同的物理内存,使其指向不同的值

9. fork在进行返回的时候,本质也是向pid_t id 值写入的过程,fork往后是有两个进程的,都有各自的id变量,对应上的是虚拟地址上的地址,同一个id在被读取的时候,当父进程和子进程通过查各自的虚拟地址,再通过页表,映射到不同的地址处,即虽是一个变量名,但在物理内存中保存的值是不一样的

二:相关细节知识

1.什么叫做地址空间?

     在32位的计算机中,有32位的地址和数据总线,而CPU要根据对应的地址总线进行访问对应的物理内存,CPU与内存之间连接的线为系统总线,内存与外设之间的为IO总线,通过这些线把数据从一个设备拷贝到另一个设备(实质为充放电的过程)

      计算机只认识二进制,即对应总线上为0/1,用每根总线上的电频有/无来标识,在内存当中就可以读取对应总线上的0/1数据,获取到要访问的地址

      地址总线上的0/1,本质就是高低电频,向内存当中寻址实际就是告诉内存要访问哪个地址,对应总线上的0/1数据,本质就是CPU向内存充电,之后就能识别高低电频,即就能识别为0/1,然后把这些0/1组合就形成一个物理地址

     磁盘把数据拷贝到内存里,实际上是把磁盘当中高低电频通过总线把数据以电脉冲的形式向物理内存特定的位置进行充电,没电的为0

     32位的计算机有32根总线,每根总线上是0/1,这样就一共有2^32种可能结果,也就是4GB,即一个32位的计算机最多能够装载4GB的内存空间

  所以地址空间就是总线排列组合形成的范围空间[0,2^32]

2.理解地址空间上的区域划分

本质就是区域划分

struct area

{

    int start;

     int end;

}

用每个start和end对空间区域进行划分,对于空间区域的调整就是调整对应的start和end

在范围内,连续的空间中,还可以再次划分直至最小,每一个最小单位都有地址,这个地址是可以直接被使用的

3.地址空间深入的理解

所谓的进程地址空间,本质是一个描述进程可视范围的大小,地址空间内一定要存在各种区域划分,对线性地址进行start和end划分

地址空间本质就是一个内核数据结构对象,类似PCB一样,地址空间也是要被操作系统所管理的:先描述,再组织

4.进程理解以及进程地址空间的意义

在这里进程的定义变为内核数据结构PCB+mm_struct+页表+程序的代码和数据

意义:让进程以统一的视角看待内存

增加进程虚拟地址空间可以让我们访问内存的时候,增加一个转化的过程,在这个转化的过程中,可以让我们的寻址请求进行审查,所以一旦异常访问,直接拦截,该请求不会到物理内存,保护了物理内存

因为有地址空间和页表的存在,将进程管理模块和内存管理模块进行解耦合

5.页表的介绍

    当创建一个进程时,要创建对应的内核数据结构PCB和mm_struct,为了进行虚拟地址和物理地址之间的转化,还需要创建对应的页表结构

在系统当中,当前正在执行进程的页表的起始地址是保存在CPU中的cr3寄存器当中的,当读取自己的代码时,操作系统和CPU首先会对代码位置进行寻址,去虚拟地址中寻找代码地址,操作系统会自动根据cr3寄存器中的地址找到对应的页表结构,将虚拟地址转化为物理地址进行使用

因为该进程在运行期间,cr3寄存器中保存的地址也叫做当前进程正在运行的临时数据(进程的上下文数据),当切换进程时会把寄存器中的内容带走,当回来时会把寄存器中的页表地址恢复,因此是不怕会找不到页表的

  

    关于代码区,字符常量区的只读是如何实现的

在磁盘当中的大文件是不能一次性都加载到内存中的,此时操作系统就会采取分批加载的方式,而如果加载过多而没有使用的话,这样的行为操作系统也是不允许的,因此就会采用惰性加载的方式,一次少加载一点,而往物理内存中加载内容是没有可读可写这样的概念的,那么在读取代码区内容的只读权限是如何实现的,则是由页表来完成的

当进程被创建的时候,先是创建对应的数据结构PCB,再加载对应的可执行程序

页表添加了读写权限的一列,用来表示访问内容的可读可写

代码区和字符常量区所匹配的页表的虚拟地址和物理地址的映射关系的标志位都是r(只读权限) 

      如何确定程序的代码和数据是在内存当中的?

这里也是有页表的一列来保证的,当为1时表示是在内存当中的,0则表示不在内存当中

当我们访问一个虚拟地址时,查看页表,先看标志位,若为1表示已经被加载,直接读取物理地址,去对应物理内存中进行访问。若为0表示还没有被加载,此时操作系统就会触发缺页中断,即找到可执行程序,将代码在物理内存中申请一块空间,并加载到内存里,将空间的地址填到页表当中,重新构建映射关系,然后再进行访问

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

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

相关文章

IoTDB 入门教程 企业篇②——IoTDB-Workbench可视化控制台

文章目录 一、前文二、首页三、实例管理四、系统管理五、查询六、测点管理 一、前文 IoTDB入门教程——导读 IoTDB-Workbench同样是通过联系天谋科技商务&#xff0c;请求免费试用的。 请求试用激活启动的操作步骤&#xff0c;详情请见&#xff1a;IoTDB 入门教程 企业篇①——…

SQL注入实例(sqli-labs/less-4)

0、初始页面 1、确定闭合符号 前两条判断是否为数值型注入&#xff0c;后两条判断字符型注入的闭合符号 ?id1 and 11 ?id1 and 12 ?id1" ?id1") 2、确定表的列数 ?id1") order by 3 -- 3、确定回显位置 ?id-1") union select 1,2,3 -- 4、爆库…

RabbitMQ 应用

目录 1. 7种工作模式 1.1 Simple&#xff08;简单模式&#xff09; 1.2 Work Queue&#xff08;工作队列&#xff09; 1.3 Publish/Subscribe&#xff08;发布/订阅&#xff09; 1.4 Routing&#xff08;路由模式&#xff09; 1.5 Topics&#xff08;通配符模式&#xff09; 1.…

Yolov8在RK3588上进行自定义目标检测(四)

参考 Yolov8在RK3588上进行自定义目标检测(一) Yolov8在RK3588上进行自定义目标检测(二) Yolov8在RK3588上进行自定义目标检测(三) YOLOV8火灾检测模型的边缘端推理 验证rknn模型 1.将转换好的rknn模型上传到板子上&#xff0c;再在板子上安装rknn-toolkit-lite2,将上面的…

Nexus3 Repository代理pypi设置与应用

目录 1. 创建Blob库并指定路径 2. 创建pypi阿里镜像源 3. 创建pypi腾讯镜像源 4. 创建一个pypi组管理 5. 配置pip 6. 下载测试 扩展&#xff1a;配置好后无法下载解决思路。 Nexus 存储库中的 Blob 存储是指一种用于存储大量非结构化数据的技术。在 Nexus 存储库的上下文…

基于YOLOv8的垃圾检测系统

基于YOLOv8的垃圾检测系统 (价格85) 包含 [硬纸板&#xff0c;玻璃&#xff0c;金属&#xff0c;有机废物&#xff0c;纸&#xff0c;塑料] 6个类 通过PYQT构建UI界面&#xff0c;包含图片检测&#xff0c;视频检测&#xff0c;摄像头实时检测。 &#xff08;该系统可以…

马来西亚原生静态IP注册的账号稳定吗?

马来西亚作为东南亚重要的经济体之一&#xff0c;其网络基础设施和互联网服务水平在近年来有了显著提升。静态IP作为一种固定的互联网协议地址&#xff0c;对于某些特定的网络应用和需求非常重要。本文将围绕马来西亚原生静态IP注册的账号稳定性进行探讨&#xff0c;分析其在不…

JVM—虚拟机类加载器

参考资料&#xff1a;深入理解Java虚拟机&#xff1a;JVM高级特性与最佳实践&#xff08;第3版&#xff09;周志明 1. 类加载器 JVM设计团队有意把类加载阶段中的 “通过一个类的全限定名来获取该类的二进制字节流” 这个动作放到JVM外部实现&#xff0c;这个动作的代码称为类…

classical Chinese

classical Chinese 中型娃娃暑假作业背诵 文言文《伯牙鼓琴》 1&#xff09;拿到文言文&#xff0c;先看一遍 2&#xff09;用白话文&#xff08;现代文&#xff09;翻译一次 3&#xff09;用白话文对照回去文言文&#xff08;白话文中那些需要替换回文言文呢&#xff09; 虽…

电脑入门|如何设置默认程序打开文件的软件?弄它!

前言 最近发现一件很奇葩的事情&#xff1a;电脑文件使用不合适的软件打开&#xff0c;然后就以为打不开文件了。 千万不要笑&#xff0c;这个问题是电脑小白经常遇到的。 我曾经见过有小伙伴用Photoshop打开一个.rar的文件…… 奇奇怪怪的事情总会有很多&#xff0c;毕竟谁…

【算法设计题】合并两个非递减有序链表,第1题(C/C++)

目录 第1题 合并两个非递减有序链表 得分点&#xff08;必背&#xff09; 题解 函数声明与初始化变量&#xff1a; 初始化合并链表的头节点&#xff1a; 合并两个链表&#xff1a; 处理剩余节点&#xff1a; 返回合并后的链表&#xff1a; 完整测试代码 &#x1f308;…

如何将文件转换成PDF(四种PDF虚拟打印机介绍)

Microsoft Print To PDF 这是Windows 10及以上系统自带的转换成PDF的工具 运行输入 optionalfeatures 打开可选功能&#xff0c;钩上 [Microsoft Print To PDF] 安装完成后&#xff0c;打开一个支持打印的文件类型或者网页&#xff0c;选择打印&#xff0c;在打印机界面可以看…

4.Redis数据结构通用命令

Redis数据结构 Redis是一个键值对的数据库。 key&#xff1a;大多都是String value: 类型多种多样 Redis通用命令 keys :查看所有的key 不建议在生产环境上使用keys命令&#xff0c;因为redis是单线程的&#xff0c;keys命令会搜索很长一段时间&#xff0c;搜索的期间redi…

[数据集][目标检测]金属罐缺陷检测数据集VOC+YOLO格式8095张4类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;8095 标注数量(xml文件个数)&#xff1a;8095 标注数量(txt文件个数)&#xff1a;8095 标注…

Llama3.1技术报告简要解读--附PDF

以为前些天是在炒作llama3.1泄露&#xff0c;没想到Meta在24号凌晨直接开源了&#xff0c;包括三个不同参数规模的模型&#xff08;8B、70B、405B&#xff09;&#xff0c;三个模型上下文长度都是128K&#xff0c;其中超大杯拥有4050亿参数&#xff0c;从评测指标来看必是最强开…

基于MPC在线优化的有效集法位置控制器simulink建模与仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 5.完整工程文件 1.课题概述 模型预测控制是一种基于模型的优化控制方法&#xff0c;它利用过程模型预测未来行为&#xff0c;并通过求解一个优化问题来确定最优控制序列。MPC的特点在于它能够处理系统的动…

罗汉果糖基转移酶 SgUGT94-289-3--文献精读-37

Structural insights into the catalytic selectivity of glycosyltransferase SgUGT94-289-3 towards mogrosides 关于糖基转移酶 SgUGT94-289-3 对罗汉果苷催化选择性的结构洞察 摘要 罗汉果苷是一系列从罗汉果 (Siraitia grosvenorii) 中提取的天然甜味剂。这些罗汉果苷具…

PyQt5入门

Python中经常使用的GUI控件集有PyQt、Tkinter、wxPython、Kivy、PyGUI和Libavg。其中PyQt是Qt(c语言实现的)为Python专门提供的扩展 PyQt是一套Python的GUI开发框架,即图形用户界面开发框架.。而在Python中则使用PyQt这一工具包&#xff08;PyQt5、PyQt5-tools、PyQt5-stubs&am…

数学建模--支持向量机

目录 SVM的基本原理 SVM的应用场景 实现细节与案例分析 总结 支持向量机&#xff08;SVM&#xff09;在处理非线性数据时的核函数有哪些&#xff0c;以及它们各自的优缺点是什么&#xff1f; 如何选择支持向量机的惩罚参数CC以优化模型性能和计算效率&#xff1f; 在实际…

Day17_1--AJAX学习之GET/POST传参

AJAX 简介 AJAX 是一种在无需重新加载整个网页的情况下&#xff0c;能够更新部分网页的技术。其实AJAX就可以理解为就是JS。通过AJAX也就实现了前后端分离&#xff0c;前端只写页面&#xff0c;后端生成数据&#xff01; 现在开始通过实例学习&#xff1a; 1--GET传参 <!…