进程的切换和一般执行过程
(1)关键问题
何为进程切换?就是进程调度时机到来时从就绪进程队列中能够挑选一个进程执行,占用CPU时间,那么就有两个关键问题:一是什么时间去挑选一个就绪进程(调度时机);而是如何让进程占用CPU(进程切换的过程)?
(2)硬中断与软中断
(3)进程调度时机
1)schedule函数
Linux内核通过schedule函数实现进程调度,它在运行队列中找到一个进程,把CPU分配给它。所以调用该函数一次就是调度一次,调用该函数的时机就是进程调度的时机。调用schedule函数的两种方法如下:
2)上下文
一般来说,CPU在任何时刻都处于以下三种情况之一:
运行于用户空间,执行用户进程上下文。
运行于内核空间,处于进程上下文。
#### 运行于内核空间,处理中断上下文。
3)进程调度的时机
(1)Linux的一般执行过程
1)正在运行的用户态X。
2)发生中断(包括异常、系统调用)。
3)保护现场,此时完成上下文切换。
4)中断处理过程中或中断返回前调用schedule函数,其中switch_to做了关键进程上下文切换。
5)运行用户态进程Y。
6)恢复现场。
7)完成中断上下文切换,从进程Y内核态返回到进程Y的用户态。
8)继续运行用户态进程Y。
(2)几种特殊情况
1)通过中断处理过程中的调度时机,用户态进程与内核线程之间互相切换和内核线程之间互相切换,与最一般的情况非常类似,只是内核线程运行过程中发生中断没有进程用户态和内核态的转换;
2)内核线程主动调用schedule(),只有进程上下文的切换,没有发生中断上下文的切换,与最一般的情况略简略;
3)创建子进程的系统调用在子进程中的执行起点及返回用户态,如fork;
4)加载一个新的可执行程序后返回到用户态的情况,如execve;
(3)Linux整体框架和执行过程
![]()
(4)进程调度相关代码跟踪实验
![]()
2)通过增加-S -s启动参数打开调试模式,命令如下:
qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -S -s
![]()
3)另外开一个shell命令窗口进行gdb调试并设置断点
![]()
4)打开gdb,设置断点,其中switch_to为宏定义,不能设置断点,需到context_switch函数中单步执行查看调用
![]()
![]()
![]()
![]()
中断在本质上都是软件或某些硬件发生了某情形的而通知处理器的行为,处理器进而停止正在运行的指令流,对这些通知做出相应的反应,级转去执行预定义的中断处理程序。除了主动让出CPU外,进程调度都需要在进程外进行,这就需要从进程的指令流里切换出来,中断能起到切出进程指令流的作用,中断处理程序是与进程无关的内核指令流。运行完内核代码后,CPU顺带检查一下是否需要进程调度。需要则切换进程,不需要则一路顺着函数调用堆栈正常中断返回iret,这样就自然回到原进程继续运行了。