Linux 核心--4.内存管理(7) 3.8.1 减少Page Cache和Buffer Cache的大小 Page Cache和Buffer cache中的页面将被优先考虑释放到free_area数组中。Page Cache中包含的是内存映射文件的页面,其中有些可能是不必要的,它们浪费了系统的内存。而Buffer Cache中包含的是从物理设备中读写的缓冲数据,有些可能也是不必要的。当系统中物理页面开始耗尽时,从这些cache中丢弃页面比较简单(它不需要象从内存中交换一样,无须对物理设备进行写操作)。除了会使对物理设备及内存映射文件的访问速度降低外,页面丢弃策略没有太多的副作用。如果策略得当,则所有进程的损失相同。 每次核心交换后台进程都会尝试去压缩这些cache。 它首先检查mem_map页面数组中的页面块看是否有可以从物理内存中丢弃出去的。当系统中的空闲页面数降低 到一个危险水平时,核心后台交换进程频繁进行交换,则检查的页面块一般比较大。检查的方式为轮转,每次试图压缩内存映象时,核心后台交换进程总是检查不同的页面块。这是众所周知的clock算法,每次在整个mem_map页面数组中对页面进行检查。 核心后台交换进程将检查每个页面看是否已经被page cache或者buffer cache缓冲。读者可能已经注意到共享页面不在被考虑丢弃的页面之列,这种页面不会同时出现在这两种cache中。如果页面不在这两者中任何一种之中时,它将检查mem_map页面数组中的下一个页面。 缓存在buffer cache(或者页面中的缓冲被缓存)中的页面可以使缓冲分配和回收更加有效。内存压缩代码将 力图释放在受检页面中包含的缓冲区。 如果页面中包含的所有缓冲区都被释放,这个页面也将被释放。如果受检页面在Linux的page cache中,则它会从page cache中删除并释放。 如果释放出来了足够的页面,核心交换后台进程将等待到下一次被唤醒。这些被释放的页面都不是任何进程虚拟内存的一部分,这样无须更新页表。如果没有足够的缓冲页面丢弃则交换进程将试图将一些共享页面交换出去。 3.8.2 换出系统V内存页面 系统V共享内存是一种用来在进程之间通过共享虚拟内存来实现进程通讯的机制。进程是如何共享内存将在IPC 一章中详细讨论。现在只需要说明系统V共享内存的任何区域都可以用一个shmid_ds数据结构来表示就足够了。 此结构包含一个指向vm_area的链表指针,vm_area是为每个共享此虚拟内存区域设计的结构。它们之间通过 vm_next_shared和vm_prev_shared指针来连接。每个shmid_ds数据结构包含一个页表入口,每个入口描叙物理页面与共享虚拟页面之间的映射关系。 核心交换后台进程同样使用clock算法来将系统V共享内存页面交换出去。 每次运行时,它要记得哪个共享虚拟内存区域的哪个页面是最后一个被交换出去的。两个索引可以协助它完成这项工作,其一是一组shmid_ds数据结构的索引,另一个是系统V共享内存区域的页表入口链表的索引。 这能够保证对系统V共享内存区域作出公平的选择。 由于对于给定的系统V共享虚拟内存的物理页面框号被保存在所有共享此虚拟内存区域进程的页表中,核心 交换后台进程必须同时修改所有的页表以表示页面不再在内存而在交换文件中。对于每个要交换出去的共享 页面,核心交换后台进程可以在每个共享进程的页表中的页表入口中找到它们(通过vm_area_struct数据结 构)。如果对应此系统V共享内存的页面的进程页表入口是有效的,它可以将其转变成无效,这样换出页表入口和共享页面的用户数将减一。换出系统V共享页表入口的格式中包含一个对应于一组shmid_ds数据结构的索引以及一个对系统V共享内存区域的页表入口索引。 如果所有共享进程的页表都被修改后此页面的记数为0则共享页面可以被写到交换文件中。同样指向此系统V共享内存区域的shmid_ds数据结构链表中的页表入口也被换出页表入口代替。换出页表入口虽然无效但是它包含一组打开的交换文件的索引,同时还能找到换出页面在文件中的偏移。当页面重新被带入物理内存时,这些信息十分有用。 3.8.3 换出和丢弃页面 交换后台进程依次检查系统中的每个进程以确认谁最适合交换出去。 比较好的候选者是那些可以被交换出去(有些是不可被交换出去的)并且只有一个或者几个页面在内存中的进程。只有那些包含的数据无法检索的页面才会从物理内存中交换到系统交换文件中去。 可执行映象的许多内容都可以从映象文件中读出并且可以很容易重读出来。例如,映象中的可执行指令不能被映象本身修改,所以决不会写到交换文件中去。这些页面直接丢弃就可以。当进程再次引用它们时,只需要从可执行映象文件中读入内存即可。