0


【Linux】进程地址空间

一、进程地址空间的概念

1、虚拟地址空间

以下是虚拟地址空间分布图:

操作系统会给每一个进程都创建一个独立的虚拟地址空间,虚拟地址也叫线性地址,因为虚拟地址空间中的地址是线性增长的。通过页表将虚拟地址中地址和物理内存中的地址进行一个映射,所以我们平常看到的地址都是虚拟地址空间中的虚拟地址,而不是真实的物理地址。

2、页表+MMU

操作系统会给每个进程分配一个页表,该页表使用物理地址存储。当进程使用类似 malloc 等需要映射数据时,操作系统会马上修改页表以加入新的物理内存。当进程完成退出时,内核会将相关的页表项删除掉,以便分配给新的进程

页表和MMU的作用就是可以通过映射关系,将虚拟地址空间的数据映射到物理内存中

3、写实拷贝

当进程的任何一方,尝试写入某些数据时,操作系统会先进行数据的拷贝,然后更改页表映射,最后再让尝试写入的进程对数据进行修改,操作系统这样的技术被称之为写时拷贝。写实拷贝在某些场景下,可以减少拷贝构造,进而提高效率。

二、进程地址空间的管理

因为进程之间是有独立性的,所以操作系统会给每一个进程分配一个进程地址空间,如果操作系统中存在很多的进程,为了保证每个进程能够正常运行,因此操作系统需要将每个进程的进程地址空间进行管理。

然而我们在前面也学过管理的本质:先描述,再组织。操作系统会使用一种内核数据结构对进程地址空间进行管理,操作系统会创建一个 mm_struct 的结构体。同时为每个进程创建一个 mm-struct 类型的结构体对象。

进程地址空间被分为很多的区域,例如:堆区,栈区,代码区,未初始化数据区,初始化数据区等等,操作系统会将这些区域分成一个区间[start, end],然后来维护这一区间。

struct mm_struct
{
    //代码段
    unsigned long code_start;
    unsigned long code_end;
    //初始化数据段
    unsigned long init_start;
    unsigned long init_end;
    //栈区
    unsigned long stack_start;
    unsigned long stack_end;
};

这样的话,对地址空间进行管理就比较方便了,想要对地址空间区域进行调整,只需用改变区域变量 start 和 end 就行。

三、进程地址空间的作用

1、防止地址随意访问,保护物理内存与其他进程

非法的访问或者映射,操作系统都会识别到的。一但你进行了非法的访问或者映射,操作系统就会终止掉你的程序。例如:直接使用物理地址,如果我们的代码写错了,就有可能导致越界非法访问或修改其它地址处的数据,有了虚拟地址页表的出现,如果出现进程非法访问或者非法读写的操作,页表就可以直接对其进行拦截。地址空间有效的保护了物理内存。

2、将进程管理和内存管理进行解耦合,保证进程的独立性

每一个进程都需要有独立的进程地址空间及页表,并通过页表映射到不同的物理内存中,一个进程数据的改变并不会影响另一个进程。对于父子进程也是同样的道理,父进程/子进程在修改数据时会发生写时拷贝,并不会影响彼此,所以保证了进程的独立性。

进程的独立性,使一个进程对数据的修改,而另一个进程不受影响。

3、可以让进程以统一的视角,看待自己的代码和数据

虚拟内存是操作系统欺骗进程的一种手段,进程在看待进程的时候都认为自己拥有整块内存,然后开始对着“这块内存”开始布局自己的代码和数据,但是实际上这些代码和数据到底存没存储起来,还得看操作系统,但是站在进程的角度,它是认为我们已经布局完整个内存了!进程是看不到真实物理内存的!进程只能看到进程地址空间!


本文要是有不足的地方,欢迎大家在下面评论,我会在第一时间更正。

老铁们,记着点赞加关注!!!

标签: 数学建模

本文转载自: https://blog.csdn.net/m0_63198468/article/details/131344743
版权归原作者 x一季花开成海x 所有, 如有侵权,请联系我们删除。

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

还没有评论