Linux内存管理

Linux内存管理

内存只有在进程使用的时候才有意义,我们可以这么理解,内存其实是辅助进程的一个重要资源。为什么这么理解,是因为计算机最重要的资源是CPU,而操作系统管理使用CPU的基本单元就是进程,所以能够帮助进程最大程度调度CPU资源的外在资源都是辅助资源(暂时找不到合适的表达)

既然可以这么理解,那么进程如何使用内存呢?

进程描述符PCB里面包含了操作系统管理一个进程所需要的全部信息,比如进程打开的文件,信号以及内存等,然后PCB的一个属性mm_struct管理着进程的虚拟内存,称为内存描述符。在mm_struct中,存储着进程所使用的全部内存信息。

/*
18. 进程地址空间 
    1) mm: 指向进程所拥有的内存描述符 
    2) active_mm: active_mm指向进程运行时所使用的内存描述符
对于普通进程而言,这两个指针变量的值相同。但是,内核线程不拥有任何内存描述符,所以它们的mm成员总是为NULL。当内核线程得以运行时,它的active_mm成员被初始化为前一个运行进程的active_mm值
*/
struct mm_struct *mm, *active_mm;

用图表示更清楚些:

如图示,进程的内存段包括:代码段(Text segment)、数据段(Data segment:存储已经初始化的全局变量和静态成员变量)、BSS段(未初始化的全局和静态变量)、堆、内存映射区和栈

每个内存段都对应一个vm_area_struct来描述内存区域,其中包括这块内存区域的起始和结束地址。flags标志决定了这块内存的访问权限和行为。vm_file决定这块内存是由哪个文件映射的,如果没有那就是匿名映射。

图示是/bin/gonzo进程的内存布局。程序的二进制文件映射到代码段和数据段,代码段为只读只执行,不可更改。全局以及静态的未初始化的变量映射到BSS段,为匿名映射,堆和栈都是匿名映射,因为没有相应的文件会映射到该部分。

内存映射区可以映射共享库,映射文件,或者匿名映射,所以这块内存可以是文件映射也可以是匿名映射,不同的文件映射到不同的vm_area_struct区,所以是有多少个文件映射,就会有多少个vm_area_struct。

虚拟内存不存储任何数据,它只是将地址映射到物理内存。一个vm_area_struct块是由连续的虚拟内存页组成,但是这些虚拟内存页映射的物理内存却不一定是连续。

如图示,有三个虚拟内存页映射到物理内存,还有两个没有映射。所以常驻内存RSS为12kb,虚拟内存大小为20kb,对于有映射的三个虚拟内存页,映射到的物理内存也不是连续的。

简单总结一下:

1、每个进程的内存布局都有一个vm_area_struct,而这个结构体是由连续的虚拟内存地址组成。

2、当请求内存时,先是扩展vm_area_struct或者产生一个新的vm_area_struct,但是内核此时并不会分配内存,只有等到访问这块内存发生缺页异常时才会分配。

原文链接:http://luodw.cc/2016/02/17/linux-memory/

原文地址:https://www.cnblogs.com/wangdongfang/p/13817764.html