Linux内存管理简述

周三周四这两天学习了有关内存管理的一些内容,但是相关知识原理有很多,有些看的还是没有看的很透彻,简单写一下学习收获。

  1. 为什么要内存管理
    设想起初计算机读写数据时直接从内存实际物理地址读写,如果只运行一个程序,并且程序所需内存小于计算机内存,就完全不需要管理内存,直接用就可以了,但是计算机需要多个程序一起运行,如果仍然直接读取物理地址,会造成几个问题。
    1. 不同进程间不能隔离,每一个程序都可以直接读写任意的内存物理地址,会有程序间互相影响的危险。
    2. 内存的利用率低,若要同时运行多个程序,其总需内存大于物理内存空间,就需要使用swap空间,将当前暂时不用的数据放在ROM磁盘的swap空间上,但是程序需要连续的地址空间,所以就要将整个程序放上去,不能完全利用物理内存空间,swap的读写又比较耗时。
    3. 程序每次运行的地址都不能确定,比如10m的程序,第一次可能运行在内存的第0-10m段上,第二次就在100-110m段上,程序中的变量地址,指针都要重写。
    所以内存管理就是要解决这几个问题。
  2. 虚拟内存,分块与分页
    计算机,网络中很多问题的解决,结构的设计都少不了两种方式,分层和切割。内存管理总的来说也是通过这两个方式实现的。首先是运用了虚拟内存这一个分层,把程序和物理内存隔离开。首先明确一下,虚拟内存和磁盘的swap空间是两回事,虚拟内存所相对应的是物理内存。然后是通过内存的分段与分页,将程序的数据分割开来。
    运用虚拟内存后,每个程序都被分配了n块4GB的虚拟内存空间,在虚拟内存空间中,程序运用逻辑地址,或者叫做虚拟地址来访问虚拟内存,之后虚拟内存再通过分段或者分页的方法映射到物理内存上。
    
    这样做的好处有很多,第一,程序不会直接访问到物理地址,每个程序只访问自己独立的空间,程序之间就不会有干扰,第二,程序中运行的地址只用写虚拟地址,这样不管物理地址怎么变,程序也不用重写。第三,虚拟内存可以大于实际的内存,因为每块虚拟内存不用每时每刻和物理内存对应,程序的虚拟内存分多少都可以,只要实际运行算占用的不大于物理内存,不造成溢出就好。
    分割一开始使用的是分段,其实就是直接把程序放在虚拟内存上,没有分割,将每个程序所用的虚拟内存空间通过段号,基位置,相对位置,段长等与实际物理空间一一对应,但是这样内存的使用还是以程序为单位,内存还是得不到充分的利用,之后使用分页的方法,就相当于把程序中的数据切割,一页4kb,虚拟内存分层每页4kb的页链,物理内存也分成等大的页链,通过多级的页表一一对应,运行中的程序数据总有某个时刻在用的和不用的,我们只用读取此时在用的数据,丢弃旧页或者放在swap空间里,这样相当于细分了每个程序,让内存的使用能更加充分。
    并且Linux的内存管理和windows并不相同,即使程序关闭后,所占用的内存也并不会返回,而是进入了buff/cache中,所以随着开机时间越长,就算你当前系统没做什么,内存利用率也会越来越高,这样是为了再次运行之前用过的文件时速度更快,直接从缓存拿,如果这时候要运行需要大内存的程序,则会把缓存中旧文件数据清出,腾出地方,给新程序用,这就是为什么linux系统内存经常占用率很高,但是依然不影响使用,因为虽然free的空间少,但是buff/cache也是可用的。而windows总是留出很多空闲空间,这样的好处是启动新的程序会比较快。
    系统参数中有一个值swappiness,默认是60,这表示ram内存占用达到40%时,会启用swap空间交换数据,为0的时候表示最大限度使用ram,之后再使用swap空间,因为swap的读写要比ram慢得多,所以可以通过调小这个值来优化系统性能。