内存管理就是软硬件协同访问内存空间,主要工作:1进程请求内存时分配有效内存,2进程释放内存时回收内存,3跟踪系统的内存使用情况。最简单的内存管理当前就是进程自己找地址,自己存放,但是太复杂,因此才需要操作系统统一管理,管理方法就是虚拟内存virtual memory。程序数据很多,因此必须分割为最小单元块,正在用的在内存里,没用到的在磁盘,这个单元块就叫页。页自身也需要放在物理内存中保存,保存的总体就是页面。进程访问一个数据时,该数据在的页会导入内存,称为对页的访问,如果内存里没有页,就是缺页page fault,需要从磁盘中请求,为一次陷入trap,腾出空间(内核从内存中选一个页面,将页写会磁盘)载入新页(刚刚请求的页替代页面中缺少的部分)。页在内存与磁盘中来来回回的机制就是分页机制。
内存管理器(负责维护虚拟地址与物理地址,实现分页机制):页是内存管理的基础内存单元;硬件设备MMU完成虚拟地址变为物理地址,没有MMU物理地址和虚拟地址就是一致的。
1、页:页的结构定义参见include/linux/mm.h,一个页是可以多个进程同时访问的,还存在一种叫混合页的高级页,配置HUGE TLB PAGE SUPPORT编译选项,意思就是页可以跨页面
2、内存管理区:就是页与页间的等级关系中占据更高位置的页,linux里面有三处(ZONE_DMA用于DMA的页面,ZONE_NORMAL用于虚拟映射的非DMA页,ZONE_HIGHMEM它的地址不在虚拟地址空间中),内存管理区的区域的结构定义参见include/linux/mmzone.h
3、页面:请求页面alloc_page()和alloc__pages(),释放页面宏_free_page()和_free_pages()或free_page()和free_pages()。但是随便申请与释放肯定会导致内存碎片(叫做外部碎片,毕竟是在磁盘上)存在,因此处理内存碎片的功能就是伙伴系统bubby system,方法就是链表串起空闲页地址,从小到大,这样再申请可以找到最合适的。
4、slab分配器:其实就是打脸了上述以页为基本请求单元的设计,毕竟很多进程是按照字节申请空间的,slab分配器为此设置缓存区,用于小规模的工作。slab由缓存组成,专用缓存存储特定对象的内存,如进程描述符,大小sizeof(task_struct),通用缓存都能放,大小32、64、128...65536、131072,执行cat /proc/slabinfo就能看明白。有缓存就有缓存描述符kmem_cache_s,参见include/linux/mm/slab.c。通用缓存最大特点是成对出现(名称只差DMA,大小一样),一个是用于DMA内存管理区申请内存区(来自ZONE_DMA),一个是普通管理区申请内存区(来自ZONE_NORMAL),从而满足各种需求。通用缓存描述符参见include/linux/slab.h,通用缓存描述符存储在cache_cache专用缓存中,但slab描述符只能存在slab第一个页面里或外部第一个通用缓存里,具体存放位置在缓存创建时满足对象对齐要求后的剩余空间里。