1. 进程上下文的概念:
-
CPU的所有寄存器中的值、进程的状态以及堆栈中的内容被称 为该进程的上下文
-
操作系统管理很多进程的执行. 有些进程是来自各种程序、系统和应用程序的单独进程,而某些进程来自被分解为很多进程的应用或程序。当一个进程从内核中移出,另一个进程成为活动的, 这些进程之间便发生了上下文切换. 操作系统必须记录重启进程和启动新进程使之活动所需要的所有信息. 这些信息被称作上下文, 它描述了进程的现有状态, 进程上下文是可执行程序代码是进程的重要组成部分, 实际上是进程执行活动全过程的静态描述, 可以看作是用户进程传递给内核的这些参数以及内核要保存的那一整套的变量和寄存器值和当时的环境等
-
进程的上下文信息包括, 指向可执行文件的指针, 栈、内存(数据段和堆), 进程状态, 优先级, 程序I/O的状态, 授予权限, 调度信息, 审计信息, 有关资源的信息(文件描述符和读/写指针), 关事件和信号的信息, 寄存器组(栈指针, 指令计数器)等等, 诸如此类.
LINUX完全注释中的一段话
当一个进程在执行时,CPU的所有寄存器中的值、进程的状态以及堆栈中的内容被称 为该进程的上下文。当内核需要切换到另一个进程时,它需要保存当前进程的 所有状态,即保存当前进程的上下文,以便在再次执行该进程时,能够必得到切换时的状态执行下去。在LINUX中,当前进程上下文均保存在进程的任务数据结 构中。在发生中断时,内核就在被中断进程的上下文中,在内核态下执行中断服务例程。但同时会保留所有需要用到的资源,以便中继服务结束时能恢复被中断进程 的执行。
2. 上下文切换:
-
进程被抢占CPU时候, 操作系统保存其上下文信息, 同时将新的活动进程的上下文信息加载进来, 这个过程其实就是上下文切换, 而当一个被抢占的进程再次成为活动的, 它可以恢复自己的上下文继续从被抢占的位置开始执行.
-
上下文切换(有时也称做进程切换或任务切换)是指CPU从一个进程或线程切换到另一个进程或线程。
-
稍微详细描述一下,上下文切换可以认为是内核(操作系统的核心)在 CPU 上对于进程(包括线程)进行以下的活动:
-
挂起一个进程,将这个进程在 CPU 中的状态(上下文)存储于内存中的某处。
-
在内存中检索下一个进程的上下文并将其在 CPU 的寄存器中恢复。
-
跳转到程序计数器所指向的位置(即跳转到进程被中断时的代码行),以恢复该进程。
-
因此上下文是指某一时间点CPU寄存器和程序计数器的内容, 广义上还包括内存中进程的虚拟地址映射信息。
-
上下文切换只能发生在内核态中, 上下文切换通常是计算密集型的。也就是说,它需要相当可观的处理器时间,在每秒几十上百次的切换中,每次切换都需要纳秒量级的时间。所以,上下文切换对系统来说意味着消耗大量的 CPU 时间,事实上,可能是操作系统中时间消耗最大的操作。
-
Linux相比与其他操作系统(包括其他类 Unix 系统)有很多的优点,其中有一项就是,其上下文切换和模式切换的时间消耗非常少。
3. context_switch 进程上下文切换
linux中进程调度时, 内核在选择新进程之后进行抢占时, 通过context_switch完成进程上下文切换。
注意 进程调度与抢占的区别
-
进程调度不一定发生抢占, 但是抢占时却一定发生了调度。
-
在进程发生调度时, 只有当前内核发生当前进程因为主动或者被动需要放弃CPU时, 内核才会选择一个与当前活动进程不同的进程来抢占CPU
-
context_switch其实是一个分配器, 他会调用所需的特定体系结构的方法
-
调用switch_mm(), 把虚拟内存从一个进程映射切换到新进程中
-
switch_mm更换通过task_struct->mm描述的内存管理上下文, 该工作的细节取决于处理器, 主要包括加载页表, 刷出地址转换后备缓冲器(部分或者全部), 向内存管理单元(MMU)提供新的信息。调用switch_to(),从上一个进程的处理器状态切换到新进程的处理器状态。这包括保存、恢复栈信息和寄存器信息。
-
switch_to切换处理器寄存器的呢内容和内核栈(虚拟地址空间的用户部分已经通过switch_mm变更, 其中也包括了用户状态下的栈, 因此switch_to不需要变更用户栈, 只需变更内核栈), 此段代码严重依赖于体系结构, 且代码通常都是用汇编语言编写。
-
context_switch函数建立next进程的地址空间。进程描述符的active_mm字段指向进程所使用的内存描述符,而mm字段指向进程所拥有的内存描述符。对于一般的进程,这两个字段有相同的地址,但是,内核线程没有它自己的地址空间而且它的 mm字段总是被设置为 NULL。
-
context_switch( )函数保证:如果next是一个内核线程, 它使用prev所使用的地址空间
由于不同架构下地址映射的机制有所区别, 而寄存器等信息弊病也是依赖于架构的, 因此switch_mm和switch_to两个函数均是体系结构相关的。
context_switch()
{
struct mm_struct *mm, *oldmm;
/* 完成进程切换的准备工作 */
prepare_task_switch(rq, prev, next);
mm = next->mm;
oldmm = prev->active_mm;
arch_start_context_switch(prev);
switch_to(prev, next, prev); // 切换进程的执行环境,包括堆栈和寄存器
}
核心的切换:
-
进程切换,即esp的切换,由于从esp可以找到进程描述符。。 // esp为栈指针,用于指向栈的栈顶。
-
硬件上下文切换,设置ip寄存器的值,并jump到 switch_to 函数。
-
堆栈的切换,及ebp的切换,ebp是栈底指针,它确定了当前用户空间属于哪个进程。 // ebp为帧指针,指向当前活动记录的底部。
因此上下文是指某一时间点CPU寄存器和程序计数器的内容, 广义上还包括内存中进程的虚拟地址映射信息。因此上下文是指某一时间点CPU寄存器和程序计数器的内容, 广义上还包括内存中进程的虚拟地址映射信息。因此上下文是指某一时间点CPU寄存器和程序计数器的内容, 广义上还包括内存中进程的虚拟地址映射信息。
网友评论