能够将linux看作一个用来办理资源的程序,而其他运用程序跑在其上,linux办理运用程序的内存分配,收回,等等。为了办理,它首要需求给自己分配静态的内存空间:代码段空间,mem_map[]空间等等。然后它把剩下的其他RAM用buddy体系进行动态办理。
linux内核的pagetable swapper_pg_dir将虚拟地址0xC0000000~0xC0000000+896M映射到物理地址0x0~0x896M。除掉内核代码占用的ram外,其他的物理ram都为闲暇。当内核需求时,直接分配了就能够运用,而不需求再对swapper_pg_dir进行修正。而当用户空间需求的时分,内核为其分配page,并要修正运用进程的pagetable从而将刚分配的page映射到相应的运用进程地址空间。内核不需求再次映射,因为swapper_pg_dir现已将896M的地址映射到内核去了。除非内核运用HIGH_MEM,这时就要从头映射内核的高128M空间(修正swapper_pg_dir的高128项)。有上可知,只需运用进程分配的page小于896M(在内核地址空间之内),内核都能够直接拜访(拜见#define __copy_user(to,from,size)其间to为内核地址,运用用户page_dir的768~896项(3G~3G+896M内核空间),from运用用户地址:page_dir的0~767项(0~3G-1用户地址空间))。要是运用进程的page大于896M时,内核就不能直接拜访了,需求运用swapper_pg_dir的高128项来映射运用进程的地址空间,这也是HIGH_MEM存在的原因。
RAM的运用
1. 静态运用:用于linux代码,数据结构等所占用的ram,此类ram不需求办理。
2. 动态运用:由buddy办理。经过buddy请求的页面不运用的时分并不当即释放给buddy,而是运用3的方法缓存起来(1)由slab办理起来(2)由两个双向链表(active_list和inacTIve_list)办理的页框(3)由icache和dcache缓存起来inode和dentry。这样当体系收回的时分,也是别离经过这三个方面来收回页面,释放到buddy中去的。之所以这样,是因为经过buddy分配或释放给buddy或许需求割裂大块或许兼并小块到大的buddy中去,这样比较费时间。因而尽量将分配来的页面缓存起来。(如同linux特别喜爱搞这些缓冲,这样也就给体系带来了异步性。一般来说,异步性功率更好吧:有缓存就相当于有了流水,这样当然能够进步功率)
之所以要这样分,是因为:buddy办理睬发生很多的内部碎片,运用slab来削减碎片。一般slab是根据目标的,因而不是以页框为单位,不便于以页为单位进行换入换出。而运用双向链表是将体系中正在运用的页框串联起来,便于scan,以及页框为单位的换入换出(收回)。因而,当体系需求收回页框时,就要从slab和双向链表,inode dentry三方面考虑收回。
关于双向链表中的页框,又能够分为两种运用状况:1. 有后备文件的页框(page buffer,mmap等);2. 无后备文件的页框(运用程序的代码段,数据段,仓库段etc)。关于2,因为无后备文件,因而需求在磁盘上拓荒一个交流文件,用于寄存无后备文件的页框,这样以来,1,2都有后备文件了。有了后备文件之后,接下来需求将这些归于不同文件的页框用一个数据结构办理起来:address_space。关于有后备文件的页框,运用特定于每个文件的address_space,关于无后备文件的页框,运用体系中共用的address_space:swapper_space.这样就把1,2一致起来了。
体系要于磁盘打交道,有必要先分配一个page buffer:当需求读入文件时,首要要查找address_space看是否现已存在page_buffer,没有的话则分配一个page buffer页框,刺进address_space。当写出磁盘时,也要查看address_space中是否存在page buffer,没有的话,分配一个page buffer页框,并刺进address_space然后,将要写内容写入该page buffer并回来(该page buffer终究会被页面收回看护线程刷新到磁盘上去)。以上的操作过程相同适用无后备文件的状况(仅仅它们运用的address_space是swapper_space)。
page buffer是vfs看见(运用的)设备,而cache buffer是块驱动程序运用的设备,一个page buffer包括多个cache buffer(当然块设备也要运用cache buffer)。也就是说,vfs等上层之能“看见”页面,而基层的块设备驱动程序只能看见块。所以当vfs要将一个页写入块设备时分,有必要先将页划分红几个buffer,每个buffer用buffer_head描绘,一个页中的buffer_head运用单连表相连,只要才干被底层的设备辨认。