context_switch( )

本文详细阐述了操作系统中的上下文切换过程,通过调用context_switch()函数完成虚拟内存的进程映射切换,再利用switch_to()函数实现处理器状态的转换,包括栈和寄存器信息的保存与恢复。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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;
}













 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值