0


【Linux】进程地址空间

个人主页:东洛的克莱斯韦克-CSDN博客

祝福语:愿你拥抱自由的风

地址总线

地址总线的宽度一般是32或64。每一根总线均可表现出有电或无电(弱电),带电的总线被计算机解释为1,不带电的总线被计算机解释为0。

32根总线有 2^{32} 种0,1组合。每一种组合可以在内存中申请1比特空间,一共可以申请4294967296比特的空间,也就是4个G。这是一个程序能申请的最大空间。

2^{32}种0,1组合用十进制理解就是从0增长到了4294967296。换句话说,站在cpu的视角,cpu看到的内存空间是线性(连续)的。

那么现在可以抛出一个概念,所谓的进程地址空间就是这一段线性空间。

语言层面的内存

【C++】C++的内存管理-CSDN博客

如果一个程序要访问内存,此时这个程序一定在cpu上运行的。用语言管理的内存就是上文所说的进程地址空间

把进程地址空间划分成栈 堆 数据段 代码段 内存映射段,在进程地址空间分布如下图

把相同属性的空间放在同一块区域,不同的区域之间限定好起始位置和边界是为了高效的维护好这一段线性空间。


系统层面的内存

进程地址空间实际上是虚拟的空间。也就是说程序管理的内存是虚拟内存。

物理内存的地址是绝对的,每一个存储单元都有一个自己的编号。系统管理的是虚拟内存和物理内存。

在进程地址空间中开好的内存通过页表映射到物理空间上——在物理空间上开辟大小相同的空间存储数据。(本篇是为了讲进程地址空间,会弱化页表的概念)


进程概述

上文为了讲清进程地址空间是什么而弱化了进程的概念,现在加入进程的概念深入理解一下进程地址空间。

进程与程序:

把保存语言逻辑的文本文件编译成二进制文件便是可执行程序。cpu只能读取内存的数据,可执行程序要执行必须先加载到内存。

Linux操作系统会为该可执行程序创建一个平pcb——进程控制块。linux内核是用C语言写的,pcb实际上是一个结构体(task_struct)。可执行程序的属性放到该结构体中维护起来。

如下是**task_struct **保存可执行程序属性的分类

标示符: 描述本进程的唯一标示符,用来区别其他进程。

状态: 任务状态,退出代码,退出信号等。

优先级: 相对于其他进程的优先级。

程序计数器: 程序中即将被执行的下一条指令的地址。

内存指针: 包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针

上下文数据: 进程执行时处理器的寄存器中的数据[休学例子,要加图CPU,寄存器]。 I/O状态信息: 包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表。

记账信息: 可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等。

其他信息

通过
task_struct可以控制一个可执行程序什么时候被cpu调度,调度的时间是多少,什么时候阻塞,什么时候被回收等等。

管理好一个可执行程序还要管理好其对应的内存。上文已经提到,可执行程序的内存就是进程地址空间。

linux内核会再创建一个结构体(
mm_struct)来描述进程地址空间的属性,只要管理好这个结构体,便可以管理好程序所对应的内存。

综上,

进程 =
**task_struct 加 **mm_struct 加 可执行程序

进程地址空间优点

进程为什么不能直接访问物理内存呢?小编总结进程地址空间的三个优点

权限

【linux】root大王如何制约普通用户——权限管理-CSDN博客

物理内存只是一个硬件,一个硬件是没有权限的概念的。在页表中加入只读,可写等权限字段,那么这块物理内存便有了权限的概念

操作系统可以在进程地址空间拦截进程对物理内存的非法操作。

如越界访问,读写权限不匹配等,物理内存中存的不止一个进程的数据,如果一个进程可以随便对物理内存进行非法操作,其他进程很容易就崩溃掉。

操作系统可以杀进程,如果一个进程对内存有非法操作,这么进程一般会被系统杀掉。

如下示例,str指向的内容是不能被修改的,如果修改该进程会挂掉

 #include<stdio.h>                                                                                                                     
     
     int main()
     {
     
 char* str = "abc";

     *str = 'H';
     
       return 0;
    }    

统一

不同进程之间的数据在物理内存上可能是乱序的,但每个进程所管理的内存都是线性的,有规律的。

即使每个进程要做的任务不同,比如qq要发送消息,游戏软件要向屏幕输出对局信息等,但进程地址空间为操作系统提供了统一描述进程内存属性的模板,方便维护进程内存属性进而高效的管理进程。

计算机内存的大小一般在2G到16G不等,而进程的数量一般在十几个到几十个不等,操作系统可能会给每个进程都分配4G(32位)的空间吗?不可能,物理内存是很紧张的资源,可以理解为进程地址空间是操作系统给进程画的一张大饼。

在内存资源很紧张的时候,操作系统为一个进程创建了task_struct ,也创建了mm_struct,甚至在进程地址空间中为该进程开辟了几个G的空间,但此时大部分的代码和数据可能还在磁盘上,只在内存中加载了一部分的代码和数据。

为什么呢?因为操作系统不会做任何浪费时间和空间的事情。几个G的数据都加载到内存,但大部分数据可能并没有运算需求,也就没必要加载到物理内存。

上述行为被称作惰性加载。

其实惰性加载并不反直觉,举一个生活中的例子帮助大家理解。一个大型游戏软件都是几十个G,为什么能在4G的游戏本上流畅的跑呢,此时你的游戏本上可能还开着微信,音乐等,原因就是操作系统操作系统会采用惰性加载的方式控制物理内存。

解耦

操作系统有四大模块,进程管理,内存管理,文件管理,驱动管理。

这里提的解耦是让进程管理和内存管理的关联性降低。

有了进程地址空间后,一个进程出问题了不会影响内存管理,进而不会影响其他进程运行。



本文转载自: https://blog.csdn.net/2301_79796701/article/details/139402046
版权归原作者 东洛的克莱斯韦克 所有, 如有侵权,请联系我们删除。

“【Linux】进程地址空间”的评论:

还没有评论