虚拟内存,内核空间和用户空间

linux简化了分段机制,使得虚拟地址与线性地址总是一致的。线性空间在32为平台上为4GB的固定大小,也就是Linux的虚拟地址空间也这么大,Linux内核将这4GB的空间分为两个部分。最高的1GB(从虚拟地址0xC0000000到0xFFFFFFFF)供内核使用,称为“内核空间“。而较低的3GB(从虚拟地址0x00000000到0xBFFFFFFF),供各个进程使用,称为“用户空间”,因为每个进程可以通过系统调用进入内核,因此,Linux内核空间由系统内的所有进程共享。所以,每个进程可以拥有4GB的虚拟地址空间(也叫虚拟内存)。每个进程有各自的私有用户空间(0~3GB),这个空间对系统中的其他进程是不可见的。最高的1GB内核空间则为所有进程以及内核所共享(虽然共享,但是一个完整的虚拟地址空间就是4GB,内核空间是每个进程都要被分配的,只是他们对应相同的地址空间)。


进程的线性地址空间分为两部分:

1、从0×00000000到0xbfffffff的线性地址,无论进程运行在用户态还是内核态都可以寻址。

2、从0xc0000000到0xffffffff的线性地址,只有内核态的进程才能寻址。

用户空间不是被进程共享的,而是被进程隔离的。每个进程最大可以有3GB用户空间。所以说一个进程对一个地址的访问,与另一个进程对同一个地址的访问不冲突,因为尽管是同一个地址但因为,进程的用户空间不共享 导致他们其实并没有指向同一个地址。而对于cpu来讲,在任意的时刻,整个系统都只有4GB的虚拟地址空间,这个虚拟空间是面向进程的,所以当进程切换的时候,虚拟地址空间也会切换。所以只有此进程运行的时候,其虚拟地址空间才被CPU所知。其他时刻,其虚拟空间不被CPU所知。

一个程序编译链接后形成的是虚拟地址空间,而程序最终要运行在物理内存中。所以,虚拟地址空间必须被映射到物理内存空间中,这个映射关系需要通过硬件体系结构所规定的数据结构来建立。即段描述符表和页表,而Linux主要通过页表来进行映射。

由以上得出一个结论。如果给出的页表不同,那么CPU将某一虚拟地址空间中的地址转化成的物理地址也不同,所以每个进程都建立了页表,将每个进程的虚拟地址空间根据自己的需要映射到物理地址空间上。既然在一个时刻CPU上只能有一个进程在运行,那么当进程发生切换时,将页表也更换为相应进程的页表,这就可以实现每个进程都有自己的虚拟地址空间而互不影响。


内核空间到物理空间内存的映射

内核空间占据了每个虚拟空间中的最高1GB,但映射到物理内存却总是从最低的地址(0x00000000)开始的,所以3GB(0xC0000000)就是物理地址与虚拟地址之间的位移量,而在Linux代码中就叫做PAGE_OFFSET。

在page.h 中对内核空间中地址映射的说明及定义如下:

# define _PAGE_DFFSET              (0xC0000000)

........

#define PAGE_OFFSET                 ((unsigner long) __PAGE_OFFSET)

#define  _pa(x)                            (unsigned long) (x) - PAGE_OFFSET

#define  _va(x)                             ((void *) ((unsigned long) (x) + PAGE_OFFSET))

对于内核空间而言,给定一个虚地址x,其物理地址为x-PAGE_OFFSET,给定一个物理地址x,其虚地址为x+PAGE_OFFSET。

 这只适合内核空间的虚地址映射到物理地址,而绝不适用于用户空间。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值