现在的位置: 首页 > 综合 > 正文

context_switch( )

2013年09月02日 ⁄ 综合 ⁄ 共 1938字 ⁄ 字号 评论关闭
context_switch( )上下文切换:
  • 调用switch_mm(),把虚拟内存从一个进程映射切换到新进程中
  • 调用switch_to(),从上一个进程的处理器状态切换到新进程的处理器状态。这包括保存、恢复栈信息和寄存器信息

    The context_switch( ) function sets up the address space of next. the active_mm field of the process descriptor points to the memory descriptor that is used by the process, while the mm field points to the memory descriptor owned by the process. For normal processes, the two fields hold the same address; however, a kernel thread does not have its own address space and its mm field is always set to NULL. The context_switch( ) function ensures that if next is a kernel thread, it uses the address space used by prev.
    context_switch( )函数建立next的地址空间。进程描述符的active_mm字段指向进程所使用的内存描述符,而mm字段
指向进程所拥有的内存描述符。对于一般的进程,这两个字段有相同的地址,但是,内核线程没有它自己的地址空间而且它的 mm字段总是被设置为 NULL。context_switch( )函数保证:如果next是一个内核线程,它使用prev所使用的地址空间:

static inline
task_t * context_switch(runqueue_t *rq, task_t *prev, task_t *next)
{
    struct mm_struct *mm = next->mm;
    struct mm_struct *oldmm = prev->active_mm;

如果next是内核线程,则线程使用prev所使用的地址空;schedule( )函数把该线程设置为懒惰TLB模式
事实上,每个内核线程并不拥有自己的页表集(task_struct->mm = NULL);更确切地说,它使用一个普通进程的页表集。不过,没有必要使一个用户态线性地址对应的TLB表项无效,因为内核线程不访问用户态地址空间。
|--------------------------------------|
|   if (unlikely(!mm)) {               |
|       next->active_mm = oldmm;       |
|       atomic_inc(&oldmm->mm_count);  |
|       enter_lazy_tlb(oldmm, next);   |
|--------------------------------------|

如果next是一个普通进程,schedule( )函数用next的地址空间替换prev的地址空间
|--------------------------------------|
|   } else                             |
|       switch_mm(oldmm, mm, next);    |
|--------------------------------------|

如果prev是内核线程或正在退出的进程,context_switch()函数就把指向prev内存描述符的指针保存到运行队列的prev_mm字段中,然后重新设置prev->active_mm

|----------------------------------|
|   if (unlikely(!prev->mm)) {     |
|       prev->active_mm = NULL;    |
|       WARN_ON(rq->prev_mm);      |
|       rq->prev_mm = oldmm;       |
|----------------------------------|
    }

context_switch()终于可以调用switch_to()执行prev和next之间的进程切换了
|----------------------------------|
|   switch_to(prev, next, prev);   |
|----------------------------------|
    return prev;
}

 

抱歉!评论已关闭.