switch_mm()

switch_mm()进行用户空间的切换,更确切地说,是切换地址转换表(pgd),由于pgd包括进程 系统空间(0xc000 0000 ~ 0xffff ffff)用户空间(0x0000 0000 ~ 0xbfff ffff)的地址映射,但是由于所有进程的系统空间的地址映射都是相同的。所以实质上就是进行用户空间的切换。
  • 每个进程都有其自身的页目录表pgd
  • 读者也许会问:进程本身尚未切换,而存储管理机制的页目录指针cr3却已经切换了,这样不会造成问题吗?不会的,因为这个时候CPU在系统空间运行,而所有进程的页目录表中与系统空间对应的目录项都指向相同的页表,所以,不管切换到哪一个进程的页目录表都一样,受影响的只是用户空间,系统空间的映射则永远不变

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)) {
        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);
        load_cr3(next
->pgd);
        
if (unlikely(prev->context.ldt != next->context.ldt))
            load_LDT_nolock(
&next->context, cpu);
    }

#ifdef CONFIG_SMP
    
else {
        per_cpu(cpu_tlbstate, cpu).state 
= TLBSTATE_OK;
        BUG_ON(per_cpu(cpu_tlbstate, cpu).active_mm 
!= next);
        
if (!cpu_test_and_set(cpu, next->cpu_vm_mask)) {
            load_cr3(next
->pgd);
            load_LDT_nolock(
&next->context, cpu);
        }

    }

#endif
}

至于LDT则仅在VM86模式中才使用,所以不在我们关心之列。

将进程next的页目录表首地址next->pgd转换成物理地址,并将其写入寄存器%%cr3中
#define  load_cr3(pgdir) 
    asm 
volatile ( " movl %0,%%cr3 " : : " r "  (__pa(pgdir)))
  • 内核将新进程的页目录表的物理地址写入cr3控制寄存器时,会自动刷新旧页表的本地TLB表项












 
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值