Linux进程(四)--进程地址空间(一)

news2024/12/18 23:05:11

       前言:在Linux中,每个正在运行的进程都有自己独立的虚拟地址空间,该虚拟地址空间是逻辑上的抽象,用于在进程间提供隔离和保护。它将进程的内存分配和访问从物理内存中分离出来,为每个进程提供了一个独立的地址空间。这究竟是怎么一回事?本文我们一起来了解一下~~

那我们话不多说,Linux,启动!!!

目录

1.程序空间地址

程序地址空间回顾

堆栈相对而生

命令行参数和环境变量

2.进程地址空间

虚拟地址&物理地址

地址空间和区域划分​​​​​​​

进程地址空间存在的意义

<1> 使得无需内存数据变得有序

<2> 增强数据访存的安全性

OS是如何将进程与页表相对应的,又是如何将虚拟地址转换为物理地址的?

<3> 将进程管理和内存管理更好的解耦

Linux中的挂起状态

页表映射实现进程独立性


1.程序空间地址

程序地址空间回顾

我们在学习C/C++的时候,肯定知道一些关于程序分布的相关结构图,如下:

那现在我们学了Linux的相关知识,在理解了冯诺依曼计算机体系的基础上,就有了这样的疑问,这个结构到底是不是内存呢?下面我们不妨来验证一下,

我们给出Linux下的这样一段代码和运行结果,用于显示各种变量的地址,

堆栈相对而生

       堆向上生长,栈向下生长,我们平常在写代码时经常遇到的栈溢出或者堆溢出,就是这个特性所导致的问题,我们来进行一下验证,

       这里我们需要注意的是,对于栈区变量的定义,虽然其是向下生长的,但是这只是对于变量的定义来说的,比如数组,结构体之类的具有连续空间的结构,其在栈区的使用是向上增长的,我们平常看到的经验来说,我们定义数组a[10],都是下标小的对应的地址比下标大的要小,对于结构体也是一样,数据成员中,最后一个声明的往往具有较大的地址值,换句话来说,栈区的使用是整体向下增长,但是对于局部变量来说,是向上增长的。

命令行参数和环境变量

        命令行参数和环境变量表保存在栈区地址上方,具体,我们可以再来验证:

2.进程地址空间

虚拟地址&物理地址

 还记得我们前面在学习父子进程,fork函数的时候留下的疑问吗?

         现在,我们再次将这个问题复现,为了能够对这个返回值做修改操作,并且我们已经知道了fork函数创建的子进程和父进程共享一份代码和不共享数据,子进程会根据需要将数据做写时拷贝保存到自己的数据信息中,而对于fork函数创建父子进程来说,父进程的完整的代码都能被子进程看到和共享(fork函数之前的代码也是),于是,我们可以利用一个全局变量 g_val,将其在父子进程做不一样的操作,来分别验证父子进程中的同一个变量的地址和数据的变化,我们给出如下的测试代码:

对同一个地址进行读取,竟然读取到了不同的值,这种现象我们该如何理解呢?计算机不会骗我们,说明这种现象肯定是正确的,所以,我们只能按照现象做出符合该现象的假设:这个地址,绝对不是物理地址!

       事实上,我们平时看到的,用到的地址,其实都是虚拟地址/线性地址,我们上面展示的程序空间结构图,其实专业的叫做进程地址空间每一个进程在被创建时都有一个属于自己的进程地址空间,在这个进程地址空间上是不能存储数据的,需要特定的方式将进程地址空间上的地址以某些映射关系映射到真实的物理地址上去,为了先大致了解这其中的原理,我们先对上面的现象做出解释,然后再其原理进行分析。

       父进程在运行时,会有一个自己专门的进程地址空间,专门用于保存进程/虚拟地址的,这个虚拟地址要想和物理地址建立联系,就需要存在一定的映射关系,我们将这种映射关系称为页表,父进程通过页表,将虚拟地址映射到物理地址上去,就能找到数据真正存储的位置并且获取它的值。而子进程可以共享父进程的代码,同样也可以共享父进程所创建的进程地址空间和页表,使得此时父子进程中的同一个全局变量当前是执指向同一个物理地址的。

        子进程被创建时会进程父进程的信息,包括大部分PCB,进程地址空间、页表等信息,此时父子进程中的全局变量是真真正正的同一个变量。

可是,一旦当子进程想要尝试修改数据,此时就需要子进程进行写时拷贝操作。当子进程发现该变量还有别的进程正在使用时,而进程具有独立性,我们不能影响别的进程的使用,所以,操作系统就在物理内存中单独给该子进程开辟了一段空间,一旦子进程想要修改数据,发生写时拷贝,此时子进程变量实际的物理地址就会改变,并且会修改其对应的页表映射关系。

地址空间和区域划分

       每个进程都有一个地址空间,操作系统为每一个进程画了一个大饼,它们都认为自己在独占物理内存,系统中存在大量进程,需要管理地址空间,那么就需要先描述、再组织进程地址空间本质上在内核中是一个数据类型 ,可以定义具体的进程地址空间变量,在Linux当中进程地址空间具体由结构体mm_struct实现。

struct mm_struct
{
 	//进程地址空间   
};

       我们的进程地址空间在开辟时就已经为每一段空间做出了区域划分,像我们上面所介绍的代码区、常量区、栈区、堆区等等,从而我们可以这样描述一个进程地址空间的结构体,我们在描述进程地址空间时,是以虚拟地址为标准来描述的,

struct mm_struct
{
    unsigned int code_start;  
    unsigned int code_end;  

    unsigned int init_data_start;
    unsigned int init_data_end;

    unsigned int uninit_data_start;
    unsigned int uninit_data_end;

    //....
    unsigned int stack_start;
    unsigned int stack_end;
};

进程地址空间存在的意义

      为什么要如此麻烦的将物理内存地址映射成虚拟地址才能被我们使用,为何不直接在PCB中以物理地址的方式存储地址?这里给出以下的几点原因:

<1> 使得无需内存数据变得有序

       首先,我们知道,进程在加载到内存的时候是随机选择内存地址的,一个进程的代码和数据在内存中被分别随机加载到任意位置,这就让我们的进程的寻址变得困难,但是引入了进程地址空间,通过进程地址空间+页表的方式,我们可以用统一的虚拟地址空间来映射物理内存的地址,可以将乱序的内存数据变得有序,方便统一管理和规划。

       同时,如果进程在执行期间发生了挂起或者进程切换导致了代码和数据的内存地址发生改变,我们只需要将页表的物理地址部分锦绣修改即可,无需对虚拟地址进程修改,方便了管理。

<2> 增强数据访存的安全性

      不知道你是否有这样一个疑问,就是进程地址空间是如何区分这些划分出来的区域的?比如字符常量区的数据为什么不能被修改这样的访存权限问题。事实上,这和我们的页表结构有关,我们的页表除了有虚拟地址和物理地址间的映射关系结构以外,对于每个映射关系,还存在一个访问权限字段这个字段就可以表示规定好的区域划分后的各个空间所具有的特殊的权限问题,比如我们的字符常量区,页表在创建时,就会识别对应的字符常量区的虚拟地址范围,并将其权限设置为只读(r),这样,我们在通过虚拟地址经过页表寻找物理地址并试图进行修改操作时,就因为页表的访问权限字段而被拦截下来,换句话说,物理地址是无法直接拦截访存操作的,是通过页表进行拦截的。

OS是如何将进程与页表相对应的,又是如何将虚拟地址转换为物理地址的?

      操作系统中可能会有众多的页表,那么操作系统是如何找到当前进程所对应的那个页表的呢?事实上,我们知道,每一个进程在需要页表的时候一定是进程正在被执行,此时CPU内部有一个特殊的寄存器(CR3),该寄存器存储的就是当前正在执行的进程的页表的物理地址 ,当该进程在CPU上执行时,通过CR3就能找到进程对应的页表信息。页表信息本质上也是保存在进程PCB中的一个结构体数据,这就使得在进程切换时,页表也能够根据上下文信息进行对应的切换,从而实现页表随进程的动态切换

     CPU通过内存管理单元(MMU)来执行虚拟地址到物理地址的转换。CPU使用虚拟地址进行内存访问, CPU内部的MMU获取虚拟地址,并将其拆分成不同的部分,通过对其进行相应的查找和执行过程找到对应的物理地址,这个过程我们不展开,后续的内容会深入的了解其转换机制。

<3> 将进程管理和内存管理更好的解耦

Linux中的挂起状态

        可执行程序在执行时,不一定需要全部加载到内存,当可执行程序过大,操作系统并不需要将这个可执行全部加载到内存,甚至是根据需要再进行加载到内存。

        在PCB的页表结构中,还存在着这样一个字段,该字段的作用就是标识在当前映射关系下,虚拟地址(在页表中,虚拟地址是可以是固定在页表左栏的,因为虚拟地址是固定的,但是映射关系是不固定的,也就是虚拟地址所映射的物理地址是不固定的,需要靠操作系统进行分配)是否分配了对应的物理地址。在执行可执行程序的部分代码时,能够根据需要将部分代码片段加载内存中,申请部分物理空间,然后将该物理地址加入到映射关系中去,而我们能看到的,只是进程地址空间上的虚拟地址,至于程序的部分加载分配到内存,和将物理地址加入到进程页表中的操作,也就是内存管理模块,对我们来说是透明的,其中,进程在访问虚拟地址时,发现其物理地址还没有被分配,从而进入暂停等待物理内存分配的过程,叫做缺页中断,这个我们后续再做深入了解,现在,我们只是知道,这是Linux进程挂起的一种状态即可。

页表映射实现进程独立性

      在Linux中,页表映射是实现进程独立性的关键机制之一。每个进程在Linux中都有自己独立的虚拟地址空间,页表映射就是将进程的虚拟地址映射到物理内存的过程。

        当一个进程进行内存访问时,CPU会使用虚拟地址进行内存访问。此时,由于虚拟地址空间和物理地址空间不同,需要通过页表来进行地址转换。

        这种方式使得每个进程可以拥有自己独立的地址空间,互相之间的内存访问不会相互干扰。同时,页表的机制还有助于实现内存保护、内存共享和内存分配等功能。

   

未完待续......

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

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

相关文章

【试题036】赋值运算符小例题2

1.题目&#xff1a;设int a0&#xff0c;b0&#xff0c;m0&#xff0c;n0;,执行(mab)/(nab)后m和n的值分别&#xff1f; 2.代码分析&#xff1a; int main() {//设int a0&#xff0c;b0&#xff0c;m0&#xff0c;n0;,执行(mab)/(nab)后m和n的值分别int a 0,b 0,m 0,n 0,…

openCV的CUDA GPU 版本安装 (Ubuntu windows 通用)

需要做template match, 比较注重时间&#xff0c;因此opencv 的普通版本不适用。需要用GPU 的。 下载 git clone https://github.com/opencv/opencv.git git clone https://github.com/opencv/opencv_contrib.git确保准备好以下内容 1&#xff1a; visual studio &#xff0…

吉利银河L6顶配续航测试 记录 方便后续对比

智能模式 不设置保电&#xff08;优先用电&#xff09;强动能回收&#xff0c;7成道路开启了L2辅助驾驶。基本无急加速&#xff0c;急减速。 空调开了不到20min 驾驶总时长&#xff1a;3h 5min,平均车速&#xff1a;35Km/h 充电&#xff1a; 慢充到100% 胎压&#xff1a; 2…

使用树莓派(香橙派)搭建文件共享服务器-samba服务器

域网内部通过文件共享来传输文件是一种非常方便的方式&#xff0c;小米摄像头也支持用文件共享smb模式将视频备份到局域网中的文件服务器上。之前我一直使用荣耀pro路由器游戏版&#xff0c;是自带USB接口支持文件共享服务的&#xff0c;接上USB移动硬盘&#xff0c;小米摄像头…

推荐收藏系列!2万字图解Hadoop

今天我用图解的方式讲解pandas的用法&#xff0c;内容较长建议收藏&#xff0c;梳理不易&#xff0c;点赞支持。 学习 Python 编程&#xff0c;给我的经验就是&#xff1a;技术要学会分享、交流&#xff0c;不建议闭门造车。一个人可能走的很快、但一堆人可以走的更远。如果你…

Spring AOP 详细深入讲解+代码示例

Spring AOP 这里是引用 一&#xff0c;介绍 spring aop工作原理图 1.什么是spring aop Spring AOP&#xff08;Aspect-Oriented Programming&#xff09;是Spring框架提供的一种面向切面编程的技术。它通过将横切关注点&#xff08;例如日志记录、事务管理、安全性检查等&a…

solidworks 2024新功能之-让您的工作更加高效

您可以创建杰出的设计&#xff0c;并将这些杰出的设计将融入产品体验中。为了帮您简化和加快由概念到成品的产品开发流程&#xff0c;SOLIDWORKS 2024 涵盖全新的用户驱动型增强功能&#xff0c;致力于帮您实现更智能、更快速地与您的团队和外部合作伙伴协同工作。 SOLIDWORKS…

【JavaEE初阶】 线程池详解与实现

文章目录 &#x1f334;线程池的概念&#x1f384;标准库中的线程池&#x1f340;ThreadPoolExecutor 类&#x1f6a9;corePoolSize与maximumPoolSize&#x1f6a9;keepAliveTime&#x1f6a9;ThreadFactory&#x1f6a9;workQueue&#x1f6a9;RejectedExecutionHandler handl…

思科披露新的IOS XE零日漏洞,用于部署恶意软件植入

导语&#xff1a;思科最近披露了一个新的高危零日漏洞&#xff08;CVE-2023-20273&#xff09;&#xff0c;该漏洞被积极利用来在已经通过本周早些时候披露的CVE-2023-20198零日漏洞遭到侵害的IOS XE设备上部署恶意植入物。 漏洞披露 思科最近披露了一款名为CVE-2023-20273的高…

Leetcode-Easy题解1-回文数字

目录 解法1解法2 解法1 自己的想法,直接转成字符串首尾俩下标同时遍历比较 class Solution {public boolean isPalindrome(int x) {if(x<0){return false;}String strString.valueOf(x);int i0;for (;i<str.length()>>1;i){if(str.charAt(i)!str.charAt(str.leng…

Unity中Shader阴影的接收

文章目录 前言一、阴影接受的步骤1、在v2f中添加UNITY_SHADOW_COORDS(idx),unity会自动声明一个叫_ShadowCoord的float4变量&#xff0c;用作阴影的采样坐标.2、在顶点着色器中添加TRANSFER_SHADOW(o)&#xff0c;用于将上面定义的_ShadowCoord纹理采样坐标变换到相应的屏幕空间…

DC-4 靶机

DC_4 信息搜集 存活检测 详细扫描 后台网页扫描 网页信息搜集 只有一个登陆界面 漏洞利用 尝试使用 burpsuite 密码爆破 尝试使用用户名 admin 登录管理员页面 成功爆破出密码 happy 登录管理员页面 显示可以使用命令 但只能使用三个命令 继续使用 bp 拦截查看数据包…

【C++】VS2019,关于scanf等的报错及其解决方案

参考资料&#xff1a;B站袁春旭老师的网课 报错一&#xff1a;this function may be unsafe. Consider using scanf_s instead. 如下图 这种错误是因为SDL检查不通过&#xff0c;默认这个检查是开的&#xff0c;如下图&#xff0c; 解决方案&#xff1a;把这个SDL检查关闭即…

5、k8s部署Nginx Proxy Manager

前言 Nginx-Proxy-Manager 是一个基于 Web 的 Nginx 服务器管理工具&#xff0c;它允许用户通过浏览器界面轻松地管理和监控 Nginx 服务器。通过 Nginx-Proxy-Manager&#xff0c;可以获得受信任的 SSL 证书&#xff0c;并通过单独的配置、自定义和入侵保护来管理多个代理。用…

51单片机KeyWard

eg1&#xff1a; 单片机键盘的分类 键盘分为编码键盘和非编码键盘&#xff0c;键盘上闭合键的识别由专用的硬件编码器实现&#xff0c;并产生键编码号或键值得称为编码键盘&#xff0c;如计算机键盘&#xff0c;而靠软件来识别的称为非编码键盘&#xff0c;在单片机组成的各种…

Python数字类型

目录 目标 版本 种类 官方文档 数据运算方法 常用函数 转整数 转浮点数 转绝对值 四舍五入 进制转换 math模块常用函数 目标 掌握Python两种数据类型的使用方法。 版本 Python 3.12.0 种类 数字类型有三种&#xff0c;分别是&#xff1a; 整数&#xff08;int&…

C++类和对象(五) 拷贝构造函数

1 概念 在现实生活中&#xff0c;可能存在一个与你一样的自己&#xff0c;我们称其为双胞胎。那在创建对象时&#xff0c;可否创建一个与已存在对象一某一样的新对象呢&#xff1f; 那在创建对象时&#xff0c;可否创建一个与已存在对象一某一样的新对象呢&#xff1f; 拷贝构造…

Linux高性能编程学习-TCP/IP协议族

一、TCP/IP协议族结构与主要协议 分层&#xff1a;数据链路层、网络层、传输层、应用层 1. 数据链路层 功能&#xff1a;实现网卡驱动程序&#xff0c;处理数据在不同物理介质的传输 协议&#xff1a; ARP&#xff1a;将目标机器的IP地址转成MAC地址RARP&#xff1a;将MAC地…

【Java基础面试四十五】、 介绍一下泛型擦除

文章底部有个人公众号&#xff1a;热爱技术的小郑。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。为何分享&#xff1f; 踩过的坑没必要让别人在再踩&#xff0c;自己复盘也能加深记忆。利己利人、所谓双赢。 面试官&#xff1a;介绍一下泛型擦除 参考…

2023年10月小程序云开发cms内容管理无法使用,无法同步内容模型到云开发数据库的解决方案

一&#xff0c;问题描述 最近越来越多的同学找石头哥&#xff0c;说cms用不了&#xff0c;其实是小程序官方最近又搞大动作了&#xff0c;偷偷的升级的云开发cms&#xff08;内容管理&#xff09;以下都称cms&#xff0c;不升级不要紧&#xff0c;这一升级&#xff0c;就导致我…