进程切换源码分析

来源:互联网 发布:电话视频软件 编辑:程序博客网 时间:2024/05/21 11:12

如有错误欢迎指正。

linux源码版本为linux-3.10.84,分析mips的进程切换。从进程A切换到进程B

  在进程切换主要实现在kernel/sched/core.c中。

  进程调度入口函数为asmlinkage void __sched schedule(void)函数。这一函数第二句语句通过sched_submit_work(tsk);这一语句来避免死锁产生,然后调用__schedule()函数进入进程调度的核心函数。

__schedule()最主要的语句为以下几句:

1. preempt_disable(); //关闭内核抢占,不允许进程调度过程中再被内核抢占。

2. rq = cpu_rq(cpu); prev = rq->curr;//把当前进程A相关的信息保存在rq,然后再使用prev来指向rq,后面全部使用prev来表示当前进程A

3. if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) //如果当前进程状态不是runnable(state只有三个状态unrunnable, runnable, stopped),并且有非阻塞等待信号。则把当前进程设置为RUNNING

4. if (unlikely(!rq->nr_running)) idle_balance(cpu, rq);//如果当前执行队列中没有正在运行的进程,那么就把其他cpu的进程弄到当前这个cpu

5. put_prev_task(rq, prev); //把之前的进程放进rq里面

6. next = pick_next_task(rq); //选择下一个进程到next,使用对应的调度策略,调用对应的调度函数来找到下一个需要被调度的进程B

7. if (likely(prev != next)) //如果进程B不是进程A,则执行调度,否则就不需要调度,只是解锁就可以了。以下步骤默认为进程B与进程A是不同进程。

8. rq->curr = next; //把当前进程指针指向需要切换的进程,这个时候基本就是确定了进程B将要被切换了,后面步骤是具体切换的内容,包括内存部分与寄存器部分。

9. context_switch(rq, prev, next); /* unlocks the rq */ //底层上下文切换

 

__schedule()中主要部分为以上9部分,下面为context_switch()函数主要语句:

1. switch_mm(oldmm, mm, next); //oldmmmm的类型为mm_struct,代表每个进程的地址空间,oldmm为进程A的地址空间,mm为进程B的地址空间, next为进程B的进程描述符。

2. switch_to(prev, next, prev);//来切换进程AB的寄存器内容,进程的context大部分是保存在寄存器中的。

 

context_switch()函数主要包含以上2部分,下面为switch_to(prev, next, last)函数:

1. 这个函数有三个参数,最后一个last在调用时候赋值为prev,进程A,这是在恢复进程A的时候需要的。

2. switch_to()调用__switch_to()__switch_to()是交换寄存器部分的信息,所以是一个针对不同指令集有不同实现的函数,在mips中调用LEAF(resume),路径为arch/mips/kernel/r4k_switch.SLEAF函数不改变静态寄存器的值,不用压栈出栈,ABI规定非静态寄存器的值也就不再用了。

3. 首先保存进程A的上下文,将CP0_STATUS保存到THREAD_STATUS(a0)中,使用cpu_save_nonscratch保存$16~$23, $29(sp), $30,以及$31,把ra保存到THEEAD_REG(a0)中,如果用到了FPU,还需要保存FPU的状态信息。

4. 然后通过PTR_L t3, TASK_THREAD_INFO(a0),恢复进程B的信息。cpu_restore_nonscratch a1。恢复 $16~$23, $29(sp), $30

5.  在恢复CP0状态信息的时候,将进程B的原来保存的第71(0xff01)替换现在CP0_STATUS{HWREna, Wired, PageMask, Context, EntryLo1, EntryLo0, Random},其中HWREna表示那些硬件寄存器可以被用户态程序访问,6-1位全部都是与MMU相关。

6. 寄存器保存于恢复结束。

 

   以上为基于mipslinux进程切换的代码分析。主要是包括运行队列状态改变,页表切换,内存地址切换,寄存器切换。

0 0
原创粉丝点击