进程切换源码分析
来源:互联网 发布:电话视频软件 编辑:程序博客网 时间: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); //oldmm与mm的类型为mm_struct,代表每个进程的地址空间,oldmm为进程A的地址空间,mm为进程B的地址空间, next为进程B的进程描述符。
2. switch_to(prev, next, prev);//来切换进程A与B的寄存器内容,进程的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.S。LEAF函数不改变静态寄存器的值,不用压栈出栈,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的原来保存的第7至1位(0xff01)替换现在CP0_STATUS,{HWREna, Wired, PageMask, Context, EntryLo1, EntryLo0, Random},其中HWREna表示那些硬件寄存器可以被用户态程序访问,6-1位全部都是与MMU相关。
6. 寄存器保存于恢复结束。
以上为基于mips的linux进程切换的代码分析。主要是包括运行队列状态改变,页表切换,内存地址切换,寄存器切换。
- 进程切换源码分析
- Linux kernel 3.10内核源码分析--进程上下文切换
- Linux进程切换分析
- 进程切换分析篇
- 进程切换过程分析
- 进程切换分析篇
- 进程切换的代码分析
- 分析进程切换宏 switch_to
- 操作系统进程切换简易分析
- init进程源码分析
- 进程启动源码分析
- init进程源码分析
- SystemServer进程源码分析
- Linux进程调度(3):进程切换分析
- 分析linux进程调度与进程切换
- 进程调度时机与进程切换分析
- cocos2dx源码分析:场景切换
- RxJava线程切换源码分析
- tomcat环境变量的配置
- linux学习笔记基础02
- 机房那些事儿---犯错之实时错误‘91
- 数据结构实验之图论二:基于邻接表的广度优先搜索遍历
- 调用Android系统设置项
- 进程切换源码分析
- CODE[VS] 3955 最长严格上升子序列(加强版)
- java_Swing之弹窗设计初次接触。
- 【图论】【强连通分量】【Tarjan】pascal+邻接表
- 博客搬迁
- 20161114
- 1.微信小程序-B站:前言准备
- Android 完美获取Ip地址
- spring boot (三) 集成 mybatis