第八周——进程切换和系统的一般执行过程
【洪韶武 原创作品转载请注明出处 《Linux内核分析》MOOC课程】
第八周——进程切换和系统的一般执行过程
一、进程调度
1.进程调度策略
Linux的调度基于分时和优先级策略
- 进程根据优先级排队,这个优先级的值表示如何适当分配CPU;
- 调度程序会根据进程的运行周期动态调整优先级,比如nice等系统调用,可以手动调整优先级;
- 内核中的调度算法相关代码使用了类似OOD中的策略模式
2.进程调度的时机
- 中断处理过程中,直接调用schedule(),或者返回用户态时根据need_resched标记调用schedule();
- 内核线程可以直接调用schedule()进行进程切换,也可以在中断处理过程中进行调度;
- 用户态进程无法实现主动调度,仅能通过陷入内核态后的某个时机点进行调度,即在中断处理过程中进行调度。
二、进程切换、进程上下文
1.进程切换
为了控制进程的执行,内核必须有能力挂起正在CPU上执行的进程,并恢复以前挂起的某个进程的执行。
2.进程上下文
- 用户地址空间:包括程序代码,数据,用户堆栈等
- 控制信息:进程描述符,内核堆栈等
- 硬件上下文
三、Linux系统的一般执行过程
1.一般过程:正在运行的用户态进程X切换到运行用户态进程Y的过程
-
中断上下文是CPU内部的切换,进程长下文切换是在内核中堆栈的切换。
- 发生中断——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)
2.特殊情况:
- 内核线程主动调用schedule(),只有进程上下文的切换,没有发生中断上下文的切换,也不需要从中断中返回
- 创建子进程的系统调用在子进程中的执行起点(如ret_from_fork)及返回用户态
- 加载一个新的可执行程序后返回到用户态的情况,如execve,在新进程内部修改了中断保存的信息
- 通过中断处理过程中的调度时机,用户态进程与内核线程之间互相切换和内核线程之间互相切换
3.地址切换:内核就是各种中断处理过程和内核线程的集合
四、Linux系统架构和执行过程
1.Linux系统的执行
- 执行gets()函数;
- 执行系统调用,陷入内核;
- 等待输入,CPU会调度其他进程执行,同时wait一个I/O中断;
- 输入ls,发I/O中断给CPU,中断处理程序进行现场保存、压栈等等;
- 中断处理程序发现X进程在等待这个I/O(此时X已经变成阻塞态),处理程序将X设置为WAKE_UP;
- 进程管理可能会把进程X设置为next进程,这样gets系统调用获得数据,再返回用户态堆栈
五、实验
启动内核,并进入调试状态—在schedule设置断点,输c运行—list查看断点所在代码段—设置断点后,设法进入其内部查看