linux内存管理 总览
linux 内存 从 内存类型角度分为
A. 虚拟内存
B. 物理内存
linux 内存 从 管理角度分为
A. 用户内存
B. 内核内存
从而 正交 形成了 4种
1. 内核物理内存
由 struct page 管理, 不同的 内存模型 有不同的管理方式
2. 内核虚拟内存
由 四种方式() 管理
3. 用户物理内存
由 struct page 管理, 不同的 内存模型 有不同的管理方式
4. 用户虚拟内存
由 task_struct 中的 mm_struct 中的 vmap_area(VMA) 管理
---------------------------------------------------------------------------------------------------总结上面的 , 即以下
内核物理内存管理方式 有4种 : 根据配置选一种
CONFIG_FLATMEM CONFIG_DISCONTIGMEM CONFIG_SPARSEMEM_VMEMMAP CONFIG_SPARSEMEM
内核虚拟内存管理方式 有5种 : 4种用于异常/内核线程/用户进程内核态,1种用于进程用户态内存
直接(线性)映射 vmalloc动态映射 持久映射kmap 固定映射fixmap之kmap_atomic(临时映射) VMA
异常 用的 物理虚拟内存 是怎么管理的 ???
.code .rodata .data .bss .stack .heap
.code .rodata .data .bss 都是 内核的,与内核线程共享
.stack 有可能是 内核栈(中断栈与内核栈共用,叫做共享中断栈,每个进程一个),有可能是独立的中断栈
.heap
还是封装的 1 2
但是注意,不能做 中断中不能做的动作(睡眠)
中断 的栈 如果采用 内核栈(sp对齐8KB,获得的是同一个值) , 应该是可以睡眠的, 因为可以用 current(就是根据sp对齐8KB获得的 ) 获取到 当前的 stack_struct , 所以就可以调用schedule
linux 内存管理 api
用户空间的内存 是 内核 管理的
glibc提供了malloc 和 mmap 函数,封装了 brk mmap 系统调用
应用程序的加载和运行 都是用的 brk mmap 系统调用 , 封装了 上面说的 3 4
内核常用的 内存申请api 是
alloc_pages函数(buddy) vmalloc函数() , 都是封装的 1 2
kmalloc函数(slab) 是 基于 1 之上,又实现了一套 物理内存的管理,虚拟内存的管理还是封装了 2
内存管理存在的问题及解决方案
内核物理内存管理方式 有4种
根据配置选一种
内核虚拟内存管理方式 有5种
4种用于异常/内核线程/用户进程内核态,1种用于进程用户态内存
以上的管理方式,不是完美的,会造成很多问题:
问题 : 内存碎片/内存不足/无法申请到连续的物理页
方案 : 内存规整/内存释放/CMA