Linux进程——程序地址空间详解

文章目录

    • 程序地址空间
      • 地址空间与物理内存
      • 什么是程序地址空间
      • 管理程序地址空间
      • 虚拟地址与物理地址的映射
      • 页表的结构及其作用
      • 程序地址空间的作用

程序地址空间

我们之前学习内存的时候,有说内存的分布大概是这样的

111b3a1ff461945fc4c793a9c6ee813e.png

其中堆由下而上,栈由上而下

除此之外,实际上C/C++的常量字符串处于正文代码区,因此常量字符串是不允许修改的

其次虽然栈是由上而下的,但是数组和结构体的地址是从下而上开辟的,简单说就是a[0]的地址比a[1]的地址低

地址空间与物理内存

我们考虑下面这样的代码

#include <stdio.h>    
#include <unistd.h>    
#include <sys/types.h>    
#include <stdlib.h>    
int main()    
{    int id=fork();    int tmp=10;    if(id==0)//子进程执行的代码    {    tmp=20;    while(1)    {    printf("子进程,tmp: %d,&tmp: %p\n",tmp,&tmp);    sleep(1);    }    }    if(id>1)//父进程执行的代码    {    while(1)    {    printf("父进程,tmp: %d,&tmp: %p\n",tmp,&tmp);    sleep(1);    }    }                                                                                                                                                                   return 0;    
}    

简单说就是先开一个进程,分别声明一个tmp,再父子进程分别打印tmp的值和地址

image.png

这里我们发现很奇怪,父子进程的值不同,因为我们改了,但是为什么地址却相同呢,同一个地址还能存两个不同的值吗

如果按照我们之前所学理解这样肯定是不行的,非要说的话,那也只是这两个值相同,实际存储的地方一定不同

出现这样的现象主要是因为这样的地址信息并非真正的物理地址,而是我们所说的程序地址空间的的地址

什么是程序地址空间

我们刚刚已经知道了,程序显示给我们的地址并非真正的物理地址,其实是虚拟地址,也称为线性地址

直接扯概念就太难受了,我们形象的来解释

操作系统是内存资源的管理者,而每一个进程都想获取操作系统手上的内存资源

但是操作系统又不好提前设定每个进程的内存大小,就只好告诉他们,我目前有32G(全部并有限)的内存,你可以来申请

这里的32G就是全部的物理内存,但是有那么多进程,不可能每个都有32G,那明显不够分的,但是每个进程又以为自己有32G

这就像老板给你画的饼,你好好努力就可以年薪百万,事实上并没有

所以每一个进程都有自己的程序地址空间,都认为他拥有全部的物理地址

管理程序地址空间

我们说管理一定是先描述后组织的

操作系统想要管理这个程序地址空间也一定是基于这个逻辑的

那么本质上来说,程序地址空间也就是一个struct结构体

111b3a1ff461945fc4c793a9c6ee813e.png

也就是用一个结构体管理这么一个空间

也就是开辟一整个大空间,确定每一个分区的起止位置,然后分别用指针管理就行

那么大概就是长这个样子的

struct addr_room
{int code_start; // 代码区起始int code_end; // 代码区结束int init_start; // 初始化区起始int init_end; // 初始化区结束int heap_start; // 堆区起始int heap_end; // 堆区结束// ......// 其他属性
};

那么想要对应的分区大一点或者小一点,其实也就是让他们的起止位置进行变化即可

虚拟地址与物理地址的映射

那么我们了解了虚拟地址之后,知道了两个相同的地址变量是有可能的,但似乎还是没有理解到,所有虚拟地址的大小的和明明是大于物理地址的,这是怎么办到的呢

实际上在虚拟地址和物理地址之间并非一一对应的映射关系,而是通过页表的哈希映射关系,而且每一个进程都有一个对应的页表来进行映射,如果你访问非法地址,那么页表层就会阻止你进行访问了

那么问题就容易解释多了

当我们创建子进程之后,原来的子进程和父进程的数据是共享的,不光是数据共享,页表指向的内容也是相同的,当我们进行修改变量值的操作时,操作系统会重新为其开辟一份物理内存,并修改子进程页表映射的后半段内容

也就是说整个访问数据过程分为两步,第一步获取虚拟地址,第二步获取页表中对应虚拟地址的物理地址,这样就能取到对应的值了

而对于这两个进程来说,他们各自有两个页表,两个变量,只是这两个变量名称相同,通过查页表的地址才能获取这两个变量的值,他们的虚拟地址相同,物理地址不同

这也是操作系统写时拷贝的深层次逻辑

页表的结构及其作用

页表还有一个作用,他不仅仅是带了地址的映射关系,还带了每个地址的访问权限,具体起来就是读写权限

这也就能解释,为什么代码区的内存无法修改,常量字符串处于代码区,也无法修改,但是编译通过运行不通过,就是这个原因,因为操作系统不同意,在访问页表的时候,页表就给他拒绝了

这就给系统的安全性加上了一道锁

其次页表还有一个作用就是代替我们程序员进行数据的分类调序,在页表映射的时候,会将不同的数据类型进行划分,让其映射到物理内存中是一种相对有序的状态,这样做也可以节省内存资源嘛

程序地址空间的作用

  1. 保护物理内存
    这一点我们刚刚有进行说明,因为页表可以控制权限,让操作系统识别到非法操作
  2. 降低操作系统耦合度
    引入页表之后,物理内存所需要做的事情就只有提供地方存数据了,具体存什么,怎么存,都不关心,物理内存的分配和进程的管理几乎完全分开
  3. 保持进程的独立性
    这样做每一个进程都认为自己拥有一整块大内存,所有复杂的操作都由操作系统以及页表完成,进程只负责用,物理内存只需要提供地方

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

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

相关文章

LeetCode:删除排序链表中的重复元素(C语言)

1、问题概述&#xff1a;给定一个已排序链表的头&#xff0c;删除重复元素&#xff0c;返回已排序的链表 2、示例 示例 1&#xff1a; 输入&#xff1a;head [1,1,2] 输出&#xff1a;[1,2] 示例 2&#xff1a; 输入&#xff1a;head [1,1,2,3,3] 输出&#xff1a;[1,2,3] 3…

2024年国际高校数学建模大赛(IMMCHE)问题A:金字塔石的运输成品文章分享(仅供学习)

2024 International Mathematics Molding Contest for Higher Education Problem A: Transportation of Pyramid Stones&#xff08;2024年国际高校数学建模大赛&#xff08;IMMCHE&#xff09;问题A&#xff1a;金字塔石的运输&#xff09; 古埃及金字塔石材运输优化模型研究…

2024最新Selenium面试题(附带答案),建议收藏备用

一.你在TestNG中使用了哪些注解&#xff1f; TestBeforeSuiteAfterSuiteBeforeTestAfterTestBeforeClassAfterClassBeforeMethodAfterMethod 二.如何从Excel中读取数据&#xff1f; FileInputStream fs new FileInputStream(“excel文件路径”); Workbook wb WorkbookFact…

探索智慧校园资产入库功能,构建高效校园资产管理体系

在智慧校园的资产管理框架下&#xff0c;资产入库功能作为资产生命周期管理的开端&#xff0c;扮演着至关重要的角色。这一功能确保了新购置或转入的资产能够迅速而准确地被记录在系统中&#xff0c;从而无缝融入日常的管理流程。当资产入库时&#xff0c;系统要求详细登记一系…

2024最新前端学习路线指南!

2024最新前端学习路线指南&#xff01; 如果你正在寻找一份全面的前端学习路线图&#xff0c;那么这份精心打造的学习大纲恰好符合您的需求。无论您是新手还是经验丰富的开发者&#xff0c;这份路线图都能够帮助您系统地掌握前端开发的关键知识点&#xff0c;并在实践中不断提…

<PLC><HMI><汇川>在汇川HMI画面中,如何为UI设置全局样式?

前言 汇川的HMI软件是使用了Qt来编写的,因此在汇川的HMI程序编写过程,是支持使用qt的样式来自定义部件样式的,即qss格式。 概述 汇川的软件本身提供三个系统的style样式,我们可以直接使用,但是,如果系统提供的样式不符合你的需求,那么你可以对其进行修改,或者自己新建…

修改linux服务器上的mariadb/mysql数据库的密码

文章目录 一、查看数据库的状态二、修改密码 可能我们在最初安装数据库时没有设置密码或者已经设置了但是又想修改另一个密码&#xff0c;可以这样操作来修改我们的密码。 以数据库 mariadb 为例。 一、查看数据库的状态 使用命令 systemctl is-active mariadb 查看当前数据库…

Github 2024-07-27开源项目日报 Top10

根据Github Trendings的统计,今日(2024-07-27统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量非开发语言项目2C++项目2C项目2TypeScript项目1JavaScript项目1Java项目1Python项目1C#项目1免费编程学习平台:freeCodeCamp.org 创建周期:33…

JMeter接口测试:测试中奖概率!

介绍 Apache JMeter 是 Apache 组织基于 Java 开发的压力测试工具&#xff0c;用于对软件做压力测试。JMeter 最初被设计用于 Web 应用测试&#xff0c;但后来扩展到了其他测试领域&#xff0c;可用于测试静态和动态资源&#xff0c;如静态文件、Java 小服务程序、CGI 脚本、J…

Redis 缓存

安装 安装 Redis 下载&#xff1a; Releases tporadowski/redis (github.com) winr ----services.msc-----将redis 设置为手动(只是学习&#xff0c;如果经常用可以设置为自动) 安装 redis-py 库 pip install redis-py Redis 和 StrictRedis redis-py 提供 Redis 和 Str…

Java高频面试题分享

文章目录 1. 策略模式怎么控制策略的选取1.1 追问&#xff1a;如果有100种策略呢&#xff1f;1.2 追问&#xff1a;什么情况下初始化Map 2. 什么是索引&#xff1f;什么时候用索引&#xff1f;2.1 追问&#xff1a;怎么判断系统什么时候用量比较少2.2 追问&#xff1a;如何实时…

C++多态的底层原理

目录 1.虚函数表 &#xff08;1&#xff09;虚函数表指针 &#xff08;2&#xff09;虚函数表 2.虚函数表的继承--重写&#xff08;覆盖&#xff09;的原理 3.观察虚表的方法 &#xff08;1&#xff09;内存观察 &#xff08;2&#xff09;打印虚表 虚表的地址 函数 传参…

SSM电子商务系统-计算机毕业设计源码68470

基于SSM框架的电子商务系统的设计与实现 摘 要 随着电子商务的迅猛发展和计算机信息技术的全面跃升&#xff0c;网上购物系统由于其迎合了人们诉求和期望而渗入社会生活各个层面和角落。本文设计并实现了一个基于SSM框架的电子商务系统。该系统旨在为用户提供一个舒适且快捷的…

Python基础——第一个Python程序

Python基础——第一个Python程序 一、编写和运行代码的工具1.1 为什么需要工具1.2 默认的交互式环境1.3 文本编辑神器 - Visual Studio Code1.4 专业的集成开发环境 - PyCharm 二、编写第一个Python程序2.1 在PyCharm中编写“Hello, World!”程序2.2 运行“Hello, World!”程序…

Windows 11+Visual Studio 2022 环境OpenCV+CUDA 12.5安装及踩坑笔记

周六日在家捣腾了一下&#xff0c;把过程记录下来。 前置条件 Visual Studio C 生成工具和本机显卡适配的CUDA与CUDA匹配的cuDNNPython 3NumPyOpenCV源代码以及对应版本的OpenCV-contrib模块源码CMake Visual Studio 下载Visual Studio&#xff08;我本机的是VS2022&#xf…

【2024最新华为OD-C/D卷试题汇总】[支持在线评测] 智能驾驶(200分) - 三语言AC题解(Python/Java/Cpp)

🍭 大家好这里是清隆学长 ,一枚热爱算法的程序员 ✨ 本系列打算持续跟新华为OD-C/D卷的三语言AC题解 👏 感谢大家的订阅➕ 和 喜欢💗 🍿 最新华为OD机试D卷目录,全、新、准,题目覆盖率达 95% 以上,支持题目在线评测,专栏文章质量平均 93 分 最新华为OD机试目录: …

【Golang 面试基础题】每日 5 题(九)

✍个人博客&#xff1a;Pandaconda-CSDN博客 &#x1f4e3;专栏地址&#xff1a;http://t.csdnimg.cn/UWz06 &#x1f4da;专栏简介&#xff1a;在这个专栏中&#xff0c;我将会分享 Golang 面试中常见的面试题给大家~ ❤️如果有收获的话&#xff0c;欢迎点赞&#x1f44d;收藏…

c/c++的内存管理(超详细)

一、c/c的内存分布 这是操作系统中对于内存的划分&#xff1a; 我们重点掌握以下几个区域即可&#xff1a; 1.栈 (调用函数会建立栈帧) 2.堆(动态开辟的空间) 3.数据段(静态区)&#xff1a;存放静态变量以及全局变量 4.代码段 (常量区) 先来看看一个题目&#xff1a; int…

蓝牙耳机百元之内怎么选?四款百元精品爆款蓝牙耳机盘点

在蓝牙耳机的海洋中&#xff0c;百元价位仿佛是一片神秘的绿洲&#xff0c;既诱人又充满未知&#xff0c;如何在众多选项中挑选出真正的精品呢&#xff1f;蓝牙耳机百元之内怎么选&#xff1f;这是许多消费者的共同疑问&#xff0c;带着这个疑问&#xff0c;作为蓝牙耳机发烧党…

【Python机器学习】朴素贝叶斯——条件概率

条件概率 假设现在有一个装了7块石头的罐子&#xff08;3块灰色&#xff0c;4块黑色&#xff09;&#xff0c;如果从中随机取出一块&#xff0c;灰色的可能性就是3/7&#xff0c;黑色的可能性是4/7。我们使用p(gray)来表示取到灰色石头的概率&#xff0c;其概率值可以通过灰色…