【Linux】-- 程序地址空间

news2025/1/12 1:39:44

目录

程序地址空间

进程地址空间 - 虚拟地址空间

概念引入(浅)

初步理解结构

深入理解虚拟地址

为什么要有地址空间?

程序地址空间的角度理解挂起


程序地址空间

C/C++在Linux下的程序地址空间分布:

  • 栈向低地址增长,堆向高地址增长(堆、栈相对而生
  • 正文代码区包括其中的字符常量区,只能读不能写
#include<stdio.h>
#include<stdlib.h>

int un_g_val;
int g_val = 10;

int main(int argc, char* argv[], char* env[])
{
    printf("代码区:%p\n", main);      //代码区

    char* p = "hello world";         //字面常量
    printf("字面常量:%p\n", p);

    printf("已初始化全局数据区:%p\n", &g_val);    //已初始化全局数据区

    static int num = 10;
    printf("static修饰的局部变量:%p\n", &num);    //static
    printf("未初始化全局数据区:%p\n", &un_g_val); //未初始化全局数据区
    
    char* p1 = (char*)malloc(4);
    char* p2 = (char*)malloc(4);
    char* p3 = (char*)malloc(4);
    
    printf("堆1:%p\n", p1);         //堆
    printf("堆2:%p\n", p2);         //堆
    printf("堆3:%p\n", p3);         //堆
    printf("栈1:%p\n", &p1);        //栈
    printf("栈2:%p\n", &p2);        //栈
    printf("栈3:%p\n", &p3);        //栈

    for(size_t i = 0; i < argc; ++i)
    {
        printf("argv[%d]:%p\n", i, argv[i]);
    }
    for(size_t i = 0; env[i]; ++i)
    {
        printf("env[%d]:%p\n", i, env[i]);
    }
    return 0;
}

        在我们看来,父子进程是代码共享的,所以&g_val地址相同是可以理解的,父进程具有独立性,所以子进程的g_val改变父进程的g_val不变是可以理解点,但是结合起来看,具有相同地址的变量却是不同值,就很奇怪。

        其实,这里地址并不是物理上的地址,而是:虚拟地址(线性地址)。操作系统上的地址与编程语言上的地址是不一样的,不是一个理解。几乎所有有 “地址” 的概念的语言,其所谓的地址一定不是物理地址,而是虚拟地址。在操作系统上,接触不到物理地址,都是虚拟地址,这是操作系统自我的一种保护,防止空间被随意的更改。

        虚拟地址:计算机通过软硬结合的方案,创造出的地址空间的概念。

进程地址空间 - 虚拟地址空间

概念引入(浅)

初步理解进程地址空间是虚拟地址空间的意义。(计算机的演变)

        最初,其实并没有虚拟地址空间的概念,是CPU直接对物理地址空间(内存)操作。

由于物理地址空间就是自由的空间,并未对读写设置权限,也没有违规操作的处理:

  • 物理地址空间没有隔离,每一个进程都可以修改其他进程的数据,修改内核空间中的数据。
  • 由于是直接存储于物理空间内,所以进程数据必须统一规范性放置,会出现碎片化内存浪费。
  • 内存地址随机分配,程序运行的地址不确定,CPU需要查询消耗。

初步总结:我们需要一个处理方式,使得CPU运行进程的操作是规范的,安全的;对于物理地址空间中的进程管理是合理的。


这样就有了虚拟地址空间的概念。虚拟地址空间的存在就如同一幅图,一把尺

一幅图:

        直接给进程一个 0x0000……0000 到 0xffff……ffff 的空间,并把每个区域进行划分,将代码与数据 “画” 在图(虚拟地址空间)中。CPU也无需关注物理内存的存在,只需要根据 “图” 中的位置进行访问即可,剩下的转换交给操作系统,操作系统转换 “图” 中的虚拟地址变为物理地址,然后将数据输出给CPU。也就是说:每一个进程都有一幅针对它的 “图”,这副 “图” 是每个进程私有的,而在转换的过程中就是检测CPU操作是否规范的关键所在。

        CPU根据虚拟地址空间的位置向操作系统索要数据。

一把尺:

        对于虚拟的 0x0000……0000 到 0xffff……ffff 区域的划分,区域的划分就是begin与end:

初步理解结构

         操作系统将虚拟地址空间中的地址转换为物理地址是通过所谓的页表。

        CUP通过运行进程,以进程的task_struct结构题提取到虚拟地址空间中所储存的虚拟地址,该虚拟地址再以页表的映射关系找到物理地址,再以此到物理空间中读取数据。可以说整个过程CPU都是不知道物理内存的存在的,而一直认为虚拟地址空间就是数据真正处于的位置。

地址空间和页表是每一个进程都私有的一份,以每个进程的页表的映射关系就能做到:

  • 通过映射,虚拟地址与物理地址对应,就能做到,进程之间不会互相干扰,保证进程的独立性。
  • 只有页表中的虚拟地址,或者虚拟地址相对应的物理空间才能访问。就能提高安全性,防止出现野指针越界访问其他进程的问题。

解决前面的父进程与子进程具有相同的地址,却g_val值不同的问题: 

        fork之后,代码是父子共享的,所以子进程的地址空间与页表绝大多数数据都是复制的父进程的地址空间与页表数据,二者是一样的,前提是并未在子或父进程中更改数据。

        当我们更改子进程的g_val的数据时:

        操作系统,会以实时拷贝,开辟一个空间将g_val复制拷贝,改变子进程页表的映射关系改变成新开辟的空间,然后进行子进程的g_val的数据更改。我们表面上所看的地址只是虚拟地址,其实在物理内存中,有属于自己的变量空间,只不过在用户层使用同一个变量(虚拟地址)来标识。

深入理解虚拟地址

        当我们的程序在编译的时候(形成可执行程序的时候),或者说没被加载到内存当中的时候,程序内部其实就已经有地址了。

        地址空间不仅仅是操作系统需要遵守的,其实编译器也要遵守。即编译器编译代码的时候,就已经形成了各个区域、代码区、数据区……,并且采用个Linux内核中的一样的编址方式,给每一个变量,每一行代码都进行了编址。

        所以:程序在编译的时候,每一个字段其实早就已经具有了一个虚拟地址。

        其实这正是地址空间与页表,最开始的时候的数据来源。

为什么要有地址空间?

1、凡是非凡的访问或者是映射,操作系统都会识别到,并终止此进程。

        因为地址空间和页表是操作系统创建并维护的。这也就意味着凡是想用地址空间和页表进行映射,就一定要在操作系统的监管之下来进行访问。也便保护了物理内存中所有的合法数据,包括各个进程以及内核的相关有效数据。

更直接的说就是:有效的保护了物理地址。

  • 所访问的虚拟地址是页表未有的,即访问不合法。
  • 虚拟地址所访问的物理地址是页表未映射的,即访问不合法。
  • 页表中不仅有映射关系,更有读写权限。此也是自由的物理内存,却有只能读的代码区的关键。

2、因为有地址空间和页表的存在,所以在物理内存中,可以对未来的数据进行任意的位置加载。

        由于进程与内存的联系以页表分隔。对于虚拟地址在内存中的物理地址存储,是由页表的映射而联系的,所以内存管理模块与进程管理模块就完成了解耦合。

        所以如C/C++语言上的new、malloc申请空间的时候,本质就是在虚拟空间申请。因为对于物理空间申请了,但是无法立马使用,就会造成空间的浪费,而由于两个模块的解耦合,那么两个模块的联系也就是一个页表,对于物理空间并没有立马给与的必要。只需延迟分配的策略,就可以提高整机的效率。

        之所以可以延迟分配,本质上:因为有地址空间的存在。所以地址 “许诺” 给进程就可以了,上层申请空间就是在地址空间上申请,物理内存可以一个bit为都不给。进程既不是立马运行,那就延迟实现 “许诺” ,提高内存的使用。而当你真正的对物理地址空间访问的时候,才执行内存的相关管理算法,申请空间,构建页表映射关系)

        内存管理操作系统自动完成。用户、CPU、进程完全0感知。

3、根据2,因为在物理内存中理论可以任意位置加载,那么物理内存中的几乎所有数据和代码在内存中都是乱序的。

        因为页表的存在,它可以将地址空间上的虚拟地址与物理地址进行映射,所以可以做到在进程的视角中所有的内存分布,是有序的。

        重点:地址空间+页表 = 内存乱序分布变的有序化。

        不同进程的需要访问的物理内存中的代码和数据,是由页表规范化,映射到不同的物理内存中,进而可以做到进程的独立性。

        重点:地址空间+页表 = 内存乱序分布变的独立化。

        实现的有序化、独立化,更是由于地址空间的存在。因为每一个进程都认为自己有一个4GB空间(32位),进而有了虚拟地址分布的地址空间,并通过页表映射到不同的区域,实现有序化、独立化。

程序地址空间的角度理解挂起

        加载的本质就是创建进程,按照前面第3点,并不是必须把所有程序的代码和数据加载到内存中,并创建内核数据结构建立映射关系。在极端的情况下,甚至可能只有内核结构被创建出来,并未分配物理空间,这就是未了提高内存利用率进行的分批加载,同样的也有分批换出。

        当已被执行完的代码与数据,或者由于处于对于某种资源的等待导致的阻塞,也就是此进程短时间不会再执行了。进程的数据和代码就换出,也就叫做挂起。

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

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

相关文章

透过现象看本质,我找到了Netty粘包与半包的这几种解决方案

1、粘包与半包 啥也不说了&#xff0c;直接上代码是不是有点不太友好&#xff0c;我所谓了&#xff0c;都快过年了&#xff0c;还要啥自行车 我上来就是一段代码猛如虎 1.1 服务器代码 public class StudyServer {static final Logger log LoggerFactory.getLogger(StudyS…

怎样进行股票量化对冲策略分析?

股票量化对冲策略的分析需要从各方面去深入了解&#xff0c;就比如说明确量化和对冲的概念&#xff0c;可以先下载OA系统中“量化对冲 产品基础知识的学习&#xff0c;也要知道量化对冲产品在构建股票多头的同时&#xff0c;也构建期货空头。在市场不稳定的操作情绪之下&#x…

Git——初识git

1、git概述 1.1 简介 Git 是一个免费的、开源的分布式版本控制系统&#xff0c;可以快速高效地处理从小型到大型的各种 项目。 Git 易于学习&#xff0c;占地面积小&#xff0c;性能极快。 它具有廉价的本地库&#xff0c;方便的暂存区域和多个工作 流分支等特性。其性能优于…

rtl8188eus Linux驱动移植

rtl8188eus Linux驱动移植 rlt8188eus作为无线USB网卡&#xff0c;可以给我们的Linux设备提供无线上网能力&#xff0c;也能配置为AP&#xff0c;给其它无线设备提供上网能力。在使用较低版本的内核时&#xff0c;内核中不含rtl8188eus驱动&#xff0c;因此尝试自己移植&#…

1、常见的存储设备

文章目录较为常见的存储设备机械硬盘简介固态硬盘简介U盘简介固态U盘MMC卡SD卡简介TF卡NM卡MS卡CF卡CFExpress卡磁带光盘较为常见的存储设备 目前较为常见的存储设备&#xff0c;从电脑用的&#xff1a; 机械硬盘固态硬盘U盘固态U盘 到单反相机、运动相机、手机、行车记录仪…

BigDecimal 基本使用和常用方法

背景 涉及到比较大的数字之间的计算&#xff0c;使用float、double这样的浮点数就不那么准确了。因为不论是float 还是double都是浮点数&#xff0c;而计算机是二进制的&#xff0c;浮点数会失去一定的精确度。所以在商业计算中基本要用java.math.BigDecimal 一、初始化使用…

蹭秦霄贤流量,郭德纲凌晨时分转发老秦动态

都知道德云社董事长王慧很忙&#xff0c;每天除了打理公司业务&#xff0c;还要照顾众多徒弟们的衣食住行。王慧作为德云社董事长&#xff0c;她的忙都在情理之中&#xff0c;而郭德纲作为德云社总班主&#xff0c;他的时间就更加弥足珍贵了。 可是谁能想到&#xff0c;就是这样…

VSCode配置C++开发环境:OpenCV

文章目录Linux编译调试配置OpenCVWin10编译调试配置OpenCV参考最近在做深度学习的C部署相关工作&#xff0c;于是写下这篇文档记录环境配置的过程。环境配置是一项非常繁琐的工作&#xff0c;无论从大学做相关作业还是到工作上。做这项工作需要技术的同时&#xff0c;还需要点运…

从0到1完成一个Vue后台管理项目(一、创建项目)

1.创建文件夹 这很简单&#xff0c;自己选一个盘&#xff0c;然后建一个文件夹即可 我选择的是D盘&#xff0c;最后的目录是vue-admin 注意&#xff1a;最后的目录一定要是英文 2.创建项目 初始化 npm init -y 局部安装vue-cli vue-cli的版本一直在更新&#xff0c;所以不推…

品牌舆情总结及品牌修复,品牌舆情监测监控怎么做?

如今互联网大数据时代&#xff0c;信息流通越来越快&#xff0c;影响覆盖面广。品牌一旦出现舆论&#xff0c;很容易引起大范围的热议&#xff0c;对品牌发展造成不利影响&#xff0c;进而影响品牌声誉。接下来TOOM舆情监测小编带您简单了解品牌舆情总结及品牌修复&#xff0c;…

Linux_Study

文章目录1.操作系统概述1.1 操作系统的作用1.2 常见的操作系统2.Linux介绍2.1 诞生2.2 Linux内核3. Linux基础操作3.1 虚拟机快照3.2 Linux 目录结构3.3 命令、命令行3.4 ls命令&#xff08;列表命令&#xff09;3.5 cd/pwd命令&#xff08;目录命令&#xff09;3.6 相对路径、…

OPENCPU学习---开发环境搭建

BC260Y-CN模组移远公司提供了QuecOpen的开发方案&#xff0c;可以通过提供的SDK中相应的接口快速进行应用开发。开发环境的搭建&#xff0c;首先要准备好开发板、SDK包以及下载工具&#xff0c;准备好后进行编译配置即可进行开发。目前移远提供的BC260Y开发SDK版本为&#xff1…

Lambda表达式超详细总结(简单易懂)

文章目录1、什么是Lambda表达式2、为什么使用Lambda表达式3、函数式接口&#xff08;lambda表达式的使用前提&#xff09;4、推导Lambda表达式5、Lambda表达式语法1、什么是Lambda表达式 Lambda表达式&#xff0c;也可称为闭包。其本质属于函数式编程的概念&#xff0c;是Java…

js判断元素是否在可视区域内

基本概念 首先需要搞清楚 clientHeight、scrollTop 的区别&#xff0c;通俗地说&#xff0c;clientHeight 指的是网页可视区域的高度&#xff0c;scrollTop 指的是网页被卷起来的高度&#xff0c;可以参考这篇文章&#xff1a;彻底搞懂clientHeight、offsetHeight、scrollHeig…

SQL -- MySQL 初识

SQL SQL的概述&#xff1a; SQL全称&#xff1a; Structured Query Language&#xff0c;是结构化查询语言&#xff0c;用于访问和处理数据库的标准的计算机语言。 SQL语言1974年由Boyce和Chamberlin提出&#xff0c;并首先在IBM公司研制的关系数据库系统System上实现美国国家…

入门远程连接技术

目录 1、ssh实验 要求&#xff1a;a.两台机器&#xff1a;第一台机器作为客户端&#xff0c;第二台机器作为服务器&#xff0c;在第一台使用rhce用户免密登录第二台机器。b.禁止root用户远程登录和设置三个用户sshuser1, sshuser2, sshuser3&#xff0c; 只允许sshuser3登录&…

DOM(二):节点操作、事件高级

节点操作节点层级事件高级事件对象节点概述 节点至少拥有nodeType&#xff08;节点类型&#xff09;、nodeName&#xff08;节点名称&#xff09;、nodeValue&#xff08;节点值&#xff09;这三个基本属性。 元素节点 nodeType为1属性节点 nodeType为2文本节点 nodeType为3 &…

字节前端必会vue面试题集锦

Vue3有了解过吗&#xff1f;能说说跟vue2的区别吗&#xff1f; 1. 哪些变化 从上图中&#xff0c;我们可以概览Vue3的新特性&#xff0c;如下&#xff1a; 速度更快体积减少更易维护更接近原生更易使用 1.1 速度更快 vue3相比vue2 重写了虚拟Dom实现编译模板的优化更高效的…

3、数据库中的约束数据库设计

约束 * 概念&#xff1a; 对表中的数据进行限定&#xff0c;保证数据的正确性、有效性和完整性。 * 分类&#xff1a; 1. 主键约束&#xff1a;primary key 2. 非空约束&#xff1a;not null 3. 唯一约束&#xff1a;unique 4. 外键约束&#xff1a;forei…

3.0里程碑:Topomel Box 现已在微软商店可用

猿友好&#xff01; 今天是个大喜的日子 我的程序 Topomel Box 的第三个版本(3.0)正式上架微软商店。通过微软商店这个统一的分发渠道&#xff0c;Topomel Box 有望与更多国家的用户见面并提供服务。 安装方法很简单&#xff0c;只需要打开微软商店&#xff08;Microsoft Sto…