Linux进程和内核地址空间
一、 Linux采用了虚拟内存管理技术,使得每个进程都有独立的进程地址空间,该空间是大小为3G,用户看到和接触到的都是虚拟地址。利用这虚拟地址,不但能保护操作系itongde作用,更重要的是用户程序可使用比实际物理地址内存更大的地址空间。
二、inux将4G的虚拟地址空间划分为2部分---用户空间与内核空间用户空间从0到0xbfffffff,内核空间从3G到4G,用户进程通常情况下只能访问用户空间的虚拟地址,不能访问啮合空间。例外请款情况是用户进程通过系统调用访问内核空间。
三、用户空间对应进程,每当进程切换,用户空间就会跟着变化。
catr/proc/<pid>/maps下查看每个进程运行的用户空间。
创建进程fork(),程序载入execve(),动态分配内存malloc()等进程相关的操作都需要分配内存给进程。进程申请和获得的不是物理地址,仅仅是虚拟地址。
实际的物理内存只有当进程真的去访问新获得的虚拟地址时候,才会由“请页机制”产生“缺页”异常,从而进入分配实际页框的程序。该异常是虚拟内存机制赖以存在的基本保证---它会个哦阿苏内核去为进程分配物理页,并建立对应的页表,这之后虚拟地址才实实在在的映射到物理地址上。
四、Linux内核中内存分配
1、 #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 表示分配的内存位于搞内存
2、按页分配:使用模块需要分配大块的内存。
get_zeroed_page(unsigned int flasgs) 返回指向新页面的指针,并将页面清零
__get_free_pages(unsigned int flags,unsigned int order)
分配若干个连续的页面,返回指向该内存区域的指针,但是不清零这段内存区域。
当程序用完这些页后,可以释放他们:
void free_page(unsigned long addr)
void free_pages(unsigned long adrr,unsigned long order)
如果释放的和先前分配数目不等的页面,会导致系统错误。
五:内核地址空间:固定的,不会随着进程变化而改变
六:高端内存:物理内存896M以上部分。
内核空间分布
直接映射区 8M 动态映射区 8K KMAP区(永久内存映射区) 固定映射区4K
896M(MAX) 120M(MIN) 4M 4M
七:直接映射区
从3G开始,最大896M的线性地址区间,我们称作直接内存映射区,这是因为该区域的线性地址和物理地址之间存在线性转换关系: 线性地3G+物理地址 kmallloc是直接内存映射区分配的,分配的是物理内存
物理地址区间0x100000 - --- 0x200000映射到线性地址空间就是3G+0x100000 ----- 3G+0x200000
八、动态内存映射区
该区域的地址由内核函数vmalloc来进行分配,其特点是线性空间连续,但对应的物理空间不连续。vmalloc分配的线性地址所对应的物理页可能处于低端内存,也可能处于高端内存。
九、永久内存映射区
对于896MB以上的高端内存,可使用该区域来访问,访问方法:
1、使用alloc_page(__GFP_HIGNMEM)fenpei gaodua分配高端内存页。
2、使用kmap函数将分配到的高端内存映射到该区域。
十、固定映射区
有4M的线性空间,被成为固定映射区,它和4G顶端只有4K的隔离带,固定映射区中每个地址项都服务于特定的用途,如ACPI_BASE等。通常硬件会映射到这里来。