一、进程调度时机
1、系统调用返回用户态之前
2、中断返回之前
3、内核线程主动调用schedule函数
二、进程切换基本步骤
进程环境的切换分为两步:
1、从就绪队列中选择一个进程(pick_next_task),由进程调度算法决定
2、切换进程上下文(context_switch)
进程共享cpu和寄存器,所以进程切换时要保存对应的寄存器值,这些成为cpu上下文,进程上下文包括:
1、用户地址空间:程序代码、数据和用户堆栈等
2、控制信息:进程描述符(存在内核堆栈的低地址,方便通过栈顶指针取)、内核堆栈(内核栈栈顶寄存器sp)等
3、进程的cpu上下文:相关寄存器的值(指令指针寄存器:下一条要执行的指令地址)。
内核把被切换出去的进程的cpu上下文保存在结构体变量thread_struct和内核堆栈中
进程切换需要两步:
1、切换全局目录:保证不同进程的虚拟地址转换为不同物理地址
2、切换内核堆栈和进程的cpu上下文
三、通过不同的体系结构深入理解进程上下文切换的过程
1、linux-5.4.34中x86-64体系结构为例:
schedule()函数选择新进程——>context_switch——>switch_mm切换CR3——>switch_to切换cpu上下文
切换cpu上下文
进程切换是由内核实现的,栈顶指针sp是通过进程描述符的thread.sp实现的,指令寄存器ip的切换是在内核堆栈的基础上巧妙利用call/ret指令完成的。
2、linux-5.4.34中arm64体系结构为例:
context_switch和使用switch_to是通用代码跟64位x86差不多,而switch_to的实现则于体系结构相关的代码,见arch/arm64/kernel/process.c中的cpu_switch_to
其中thread.cpu_context是保存进程上下文中关键的CPU寄存器的值