在分析地址映射过程前,先描述几个概念:
逻辑地址: 在机器语言指令中,说明操作数和指令的地址;每个逻辑地址包含段(Segment)和偏移量(Offset)两部分。
线性地址:也称为虚拟地址,在32位系统中,它是32位的无符号整型,最大可达到4G。
物理地址:就是真正物理内存上的地址
CPU位数:指CPU的ALU的宽度(ALU从寄存器取数据,寄存器从总线取数据)
也是数据总线的条数
寄存器:暂存指令,数据和位址。
- CS:代码段寄存器
- DS:数据段寄存器
- SS:堆栈段寄存器
- ES:附加段寄存器
- 地址总线:内存中定位地址
- 数据总线:内存中获取数据
- 控制总线:发0/1信号
- GDTR(全局的段描述符表寄存器) 所有进程所共享的
- LDTR (局部的段描述符表寄存器) 每个进程所私有的
- CR0 最高PG位, 0 / 1 (PG内存是否开启分页)0开启,1未开启
- CR2 保存发生缺页异常的虚拟地址
- CR3 保存当前进程页目录的起始地址
- CR4 PAE位是否开启物理地址扩展 0 / 1
- 举个例子,有一个线性地址( 虚拟地址)为0x0018ff44,可以先尝试进行转换
struct page {
page_flags_t flags; /*一组标志,也对页框所在的管理区进行编号*/
atomic_t _count; /* Usage count, see below. */
/** 页框中的页表项数目(没有则为-1)
* -1: 表示没有页表项引用该页框。
* 0: 表明页是非共享的。
* >0: 表示而是共享共享的。 */
atomic_t _mapcount; /* Count of ptes mapped in mms, to show when page is mapped
* & limit reverse map searches.*/
unsigned long private; /* Mapping-private opaque data */
struct address_space *mapping;
pgoff_t index; /* Our offset within mapping. */
struct list_head lru;
/**如果进行了内存映射,就是虚拟地址。对存在高端内存的系统来说有意义。*/
void *virtual; /* Kernel virtual address */
};
- 这里提个问题,页目录和页表是每个进程都有一份还是所有进程共享呢?
2.在Linux源代码中,进程调度函数schedule()函数中,有一个进程切换函数switch_mm()函数,每一个进程有自己的地址空间,所以进程切换会进行切换地址空间。
static inline void switch_mm(struct mm_struct *prev,
struct mm_struct *next,
struct task_struct *tsk)
{
int cpu = smp_processor_id();
if (likely(prev != next)) {
/* stop flush ipis for the previous mm */
cpu_clear(cpu, prev->cpu_vm_mask);
#ifdef CONFIG_SMP
per_cpu(cpu_tlbstate, cpu).state = TLBSTATE_OK;
per_cpu(cpu_tlbstate, cpu).active_mm = next;
#endif
cpu_set(cpu, next->cpu_vm_mask);
/* Re-load page tables */
load_cr3(next->pgd); //将下一个要调度进程的页目录地址放在cr3中
/*
* load the LDT, if the LDT is different:
*/
if (unlikely(prev->context.ldt != next->context.ldt))
load_LDT_nolock(&next->context, cpu);
}
在switch_mm()函数中有一个执行语句
load_cr3(next->pgd);
pgd存放的是当前页目录地址,这里是将页目录地址放在CR3寄存器中。CPU在执行某一个进程时,进行地址映射时默认CR3寄存器放的是当前页目录地址。所以在进程切换时,要将下一个要调度进程的页目录地址放在CR3寄存器中。
在Page Table Entry中,高20位是value(value是物理页面在磁盘swap分区中的位置),最低一位是present,
引起缺页异常的原因如下:
- 当value==0,present==0时,说明PTE对应的物理页面没有分配过;
- 当value!=0,present==0时,说明PTE对应的物理页面在交换分区当中;
- 当value!=0,present!=0时,说明PTE对应的物理页面是一个活动的页面。
- 硬件是MMU(内存管理单元),利用存放在主存中的查询表来动态翻译虚拟地址,该表的内容由OS管理;
- 软件有进程页目录,页表,CR3寄存器,全局段描述符表;
- 映射由内核提供。
- 脏页,就是被修改过数据的页。在PTE中低12位中,会有一个duty位,标记是否被修改过。 没有被修改过的页面不会交换,会被新的页面覆盖。
- DRAM缓存(动态随机存储器):虚拟存储器的缓存,再主存中缓存虚拟页。
- SRAM缓存(静态随机存储器):位于CPU和主存之间的f1,f2,f3高速缓存。 SRAM比DRAM快大约10倍,而DRAM比磁盘快100 000多倍。 DRAM对磁盘的访问时间较长,所以总是使用写回,而不是直写。
- 虚拟内存:<1>将主存看成是一个存储在磁盘上的地址空间的高速缓存; <2>为每一个进程提供一致的地址空间; <3>保护了每个进程的地址空间不被其他进程破坏。
- 虚拟地址空间:在一个带虚拟存储器的系统中,CPU从一个由2^n个地址地址空间中生成虚拟地址。