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等。通常硬件会映射到这里来。

相关推荐