先上基础,下图是Linux的内存映射模型
每一个进程都有自己的进程空间,进程空间的0-3G是用户空间,3G-4G是内核空间
每个进程的用户空间不在同一个物理内存页,但是所有的进程的内核空间对应同样的物理地址
vmalloc分配的地址可以高端内存,也可以是低端内存
0-896MB的物理地址是线性映射到物理映射区的。
内核参数和系统页表都在TEXT_OFFSET保存,除了进程除了访问自身的用户空间对应的DRAM内存页外,都要经过内核空间,也就是都要切换到内核态
内存动态申请
和应用层一样,内核程序也需要动态的分配内存,不同的是,内核进程可以控制分配的内存是在用户空间还是内核空间,前者可以用于给用户空间的堆区分配内存,eg,用户进程的用户空间的malloc最终就会通过系统调用回调内核空间的内存分配函数,此时该内存分配函数就属于该用户进程,可以给在该用户进程的堆区分配空间并返回,最终使得一个用会进程在自己的用户空间获得内存分配;后者只在内核空间分配,所以用户进程不能直接访问该空间,所以多用在满足内核程序自身的内存需求,下面是Linux内核空间申请内存常用API:
kmalloc - kfree
kmalloc申请的内存在物理内存上是连续的,他们与真实的物理地址只有一个固定的偏移,因此存在简单的转换关系。这个API 多用来申请不到一个page大小的内存。kmalloc的底层需要调用__get_free_pages,参数中表示内存类型的gtp_t flags正是这个函数的缩写,常用的内存类型有GFP_USER,GFP_KERNEL,GFP_ATOMIC几种。