linux中使用的是虚拟内存管理技术,使每个进程都有独立的进程地址空间,该空间的大小为3G,使得linux系统更为的安全,也能获取更大的空间。
linux将4G的虚拟空间划分为两个部分:用户空间和内核空间。
用户空间(userspace) 0-----0xbfffffff
内核空间(kernel space)3G----4G
而用户进程通常使用的只能是用户空间
用户空间和进程是相对应的。进程却换,用户空间则跟着切换。每个进程的用户空间是嘟噜的,互不干扰,所以有:连续的运行一个进程10次。
linux下通常用fork()来创建进程,而程序载入用execve(),动态分配则用的是malloc()
实际的物理内存只有当进程真的去访问新获取到的虚拟地址时,才会由“请页机制”产生“缺页”异常。从而进入分配实际页框的程序,通知内核分配实际的物理地址。
相关的函数:
#include<linux/slab.h>
void *kmalloc(size_t size, int flags) size 大小 flags 控制kmalloc 的行为
常用的flags; GFP_ATOMIC用在进程上下文分配(包括中断)不能睡眠。
GFP_KERNEL 进程上下文,可能会睡眠(实际的物理地址)16M-----896M
_GFP_DMA 要求分配能够DMA的内存 16M以下的。
_GFP_HIGHMEM 高端内存 896M以上的。
按页分配
get_zeroed_page(unsigned int flafs)返回的是指向新页面的指针并将页面清零。
_get_free_page() 和get_zeroed_page(unsigned int flafs)差不多。只是不会将页面清零。
_get_free_pages(flafs, unsigned int order)分配若干个页面,返回指向该内存区的指针。
void free_page(unsigned long addr)和void free_pages(add,order) 与上面申请的数目要相等的。
具体的过程可以用这图来形象的描述:
slab管理器从申请的页分配各大小的链列表,到需要的时候直接使用就好。