正文:
- 内核把物理页作为内存管理的基本单元。从虚拟内存的角度来看,页就是最小单位。
- page结构与物理页相关,而并非与虚拟页相关。
- 内核把页划分为不同的区,通过区对具有相似特性的页进行分组。Linux主要使用了四种区:ZONE_DMA,ZONE_DMA32(只能被32位设备访问),ZONE_NORMAL,ZONE_HIGHEM(这个区包含高端内存,期中的页并不能永久地映射到内核地址空间)。区的实际使用和分布是与体系结构相关的。Linux把系统的页划分为分区,形成不同的内存池,这样就可以根据用途进行分配了。
- 可以直接在内核中申请一整页或者多页内存,也可以用kmalloc()以字节为单位申请内存(kfree()释放内存)。
- gfp_mask标志:行为修饰符(表示内核应该如何分配所需的内存),区修饰符(表示从哪分配内存),类型(组合了行为修饰符和区修饰符)。
- vmalloc()函数分配的内存虚拟地址是连续的,而物理地址则无需连续,这也是用户空间分配函数的工作方式:malloc()返回的页在进程的虚拟地址空间内是连续的。而kmalloc()函数确保页在物理地址上是连续的(自然虚拟地址也是连续的),多数情况下,只有硬件设备需要得到物理地址连续的内存。
- vmalloc()函数为了把物理上不连续的页转换为虚拟地址空间上连续的页,必须专门建立页表项。而且它获得的页必须一个个地进行映射(因为物理地址不连续),这就会导致比直接内存映射大的多的TLB抖动。所以vmalloc()一般只在要获得大块内存时才使用,例如当模块被动态插入到内核中时,就把模块装载到由vmalloc()分配的内存上。
- 空闲链表包含可供使用的,已经分配好的数据结构块,当代码需要一个新的数据结构实例时,就可以从空闲链表中抓取一个,而不需要分配内存。空闲链表相当于对象高速缓存,快速存储频繁使用的对象类型。
- slab分配器扮演了通用数据结构缓存层的角色。slab层把不同对象划分为所谓高速缓存组,其中每个高速缓存组都存放不同类型的对象。每个对象类型对应一个高速缓存。
- 用户空间能够负担起非常大的栈,而且栈空间可以动态增长,相反,内核栈小且固定。当给每个进程分配一个固定大小的小栈后,不但可以减少内存的消耗,而且内核也无需负担太重的栈管理任务。每个进程的内核栈大小既依赖体系结构,也与编译时的选项有关。一般每个进程都有两页的内核栈。
- 永久映射和原子映射。
- 支持SMP的现代操作系统使用每个CPU上的数据,对于给定的处理器其数据是唯一的。一般来说,每个CPU的数据存放在一个数组中,数组中的每一项对应着系统上一个存在的处理器。
- 使用每个CPU数据减少了数据锁定,因为按照每个处理器访问每个CPU数据的逻辑,你可以不再需要任何锁;使用每个CPU数据可以大大减少缓存失效(失效发生在处理器试图使它们的缓存保持同步时),在使用时必须禁止内核抢占,否则可能发生欺骗行为。