未完待续
内存使用效率低,内存不足的时候,换入换出以进程为单位,效率低下。
内核中的页PAGE
- struct page {
- //页状态
- unsigned long flags;
- //使用计数
- atomic_t _count;
- }
页面大小可能是4K\8K等,也可能2M、4M等,操作系统以页为单位使用内存,因此需要记录每个页大小,起始地址,是否使用等,记录页信息的同时需要消耗内存,当物理内存大小一定,页的数量越多,所需要消耗在维护页表上的内存就越大。页面约大可能带来浪费越大,因为以页为申请单元,一次消耗可能并用不完一个页,那么剩下的就浪费了。
一个是管理页面的成本,一个是页面使用率均衡考虑选择合适的页面大小。
linux采用虚拟内存技术,内阁进程地址空间都是4G大小,因此对于多个进程的同一个虚拟地址会映射到不同的物理地址上,因此针对每一个进程都一个页表来标识该进程的虚拟地址和物理地址的对应关系,即页表。
假设一共4GB内存,每个页面4K,那么一共有1M个页面。每个页面维护消耗4B,维护整个4B消耗4MB的内存空间,且需要是连续的4MB空间来通过偏移维护。
一级页表访问虚拟地址,通过前20bit找到页表项,根据页表项找到对应的物理地址,根据虚拟地址的后12bit找到页内偏移,从而定位到实际物理内存。
一级页表很方便,对应关系很明确。但是需要1次占用4MB连续空间来维护页表,一个进程多使用4MB,那么系统很多进程的时候,将是一个很大的消耗。
一级页表的连续性决定了在进程创建之初就需要准备好这4M,而且内存不足的时候,可能很难一次找到4MB给一个进程,因此采用多级页表的必要性体现出来。
如下图,一级页表消耗4K*4B=16KB内存,共计有4096个页表项,对应存在4096个二级页表。每个二级页表存在256个页表项(256*4B=1kb空间),4096个二级页表共计消耗4MB空间。
每个一级页表项占用4B,保存二级页表物理地址。一级页表需要是连续的16kb(一级页表block 16KB),每个二级页表所占用的4096*1kb不要求是连续的,4096个二级页表可以以1kb的大小(二级页表block 1KB)分散在不连续的物理内存,因此进程创建之初不需要提前准备好页表维护所需要的内存。当需要映射的时候再维护使用的部分,因此使用二级页表,理论上完全可以节省空间。
但是二级页表,访问了两次物理内存,带来时间消耗难以避免,虽然缓存可以缓解,但级数越多的时候,问题越明显。
操作系统软件需要维护页表项,MMU要求需要将页表基地值给到寄存器,且地址后的页表是连续排布在内存的,这样才可以通过偏移找到位置。