内容说明
本次的内容,是一次 MOOC 课程的作业。具体的,是使用汇编对 Linux 系统调用部分进行模拟实现,从而更加直观的验证 Linux 系统的基本机制。作业声明
qianyizhou17 + 原创作品转载请注明出处 + 《Linux 内核分析》MOOC 课程 http://mooc.study.163.com/course/USTC-1000029000进程调度
1 Linux的调度策略基于分时和优先级。
1.1 进程根据优先级排队
1.2 长时间未分配到 CPU 执行的进程,优先级会上升;在 CPU 上运行较长时间的进程,优先级会下降
2 schedule 函数
2.1 Linux 中通过直接、间接调用 schedule 函数来实现进程的调度——在运行队列中找到一个进程,把 CPU 分配给他
2.2 调用方法:1. 直接调用 2. 设置 nned_resched 标志
3 中断处理过程(包括时钟中断、I/O 中断、系统调用和异常)中,直接调用 schedule(),或者返回用户态时根据 need_resched 标记调用 schedule();
4 内核线程可以直接调用 schedule() 进行进程切换,也可以在中断处理过程中进行调度,也就是说内核线程作为一类的特殊的进程可以主动调度,也可以被动调度;
5 用户态进程无法实现主动调度,仅能通过陷入内核态后的某个时机点进行调度,即在中断处理过程中进行调度。进程切换
为了控制进程的执行,内核必须有能力挂起正在 CPU 上执行的进程,并恢复以前挂起的某个进程的执行,这叫做进程切换、任务切换、上下文切换;
1 挂起正在 CPU 上执行的进程,与中断时保存现场是不同的:中断前后是在同一个进程上下文中,只是由用户态转向内核态执行;进程上下文包含了进程执行需要的所有信息
2 schedule() 函数选择一个新的进程来运行,并调用 context_switch 进行上下文的切换,在 context_switch 中调用 switch_to 宏来进行关键上下文切换
2.1 next = pick_next_task(rq, prev);//进程调度算法都封装这个函数内部
2.2 context_switch(rq, prev, next);//进程上下文切换
2.3 switch_to 利用了 prev 和 next 两个参数:prev 指向当前进程,next 指向被调度的进程Linux 系统的一般执行过程
1 最一般的情况:正在运行的用户态进程 X 切换到运行用户态进程 Y 的过程
1.1 正在运行的用户态进程 X
1.2 发生中断——save cs:eip/esp/eflags(current) to kernel stack,then load cs:eip(entry of a specific ISR) and ss:esp(point to kernel stack).
1.3 SAVE_ALL // 保存现场
1.4 中断处理过程中或中断返回前调用了 schedule(),其中的 switch_to 做了关键的进程上下文切换
1.5 标号 1 之后开始运行用户态进程 Y(这里 Y 曾经通过以上步骤被切换出去过因此可以从标号 1 继续执行)
1.6 restore_all //恢复现场
1.7 iret - pop cs:eip/ss:esp/eflags from kernel stack
1.8 继续运行用户态进程 Y
2 几种特殊情况
2.1 通过中断处理过程中的调度时机,用户态进程与内核线程之间互相切换和内核线程之间互相切换,与最一般的情况非常类似,只是内核线程运行过程中发生中断没有进程用户态和内核态的转换;
2.2 内核线程主动调用 schedule(),只有进程上下文的切换,没有发生中断上下文的切换,与最一般的情况略简略;
2.3 创建子进程的系统调用在子进程中的执行起点及返回用户态,如 fork;
2.4 加载一个新的可执行程序后返回到用户态的情况,如 execve;
Linux 进程调度、切换的分析
最新推荐文章于 2021-11-20 21:29:47 发布