liunx是多任务操作系统,但当任务数量大于CPU数量时,系统会在很短的时间内将CPU轮流分配给任务,并不是所有的任务都在同时运行。
每个任务在运行前,系统都需要事先设置好CPU寄存器和程序计数器。
CPU寄存器是CPU内置的容量小速度极快的内存,程序计数器是用来存储CPU正在执行的指令位置、或者即将执行的下一条指令位置。他们称为CPU的上下文。
CPU上下文切换指的是CPU将当前任务的CPU寄存器和程序计数器保存起来,然后加载新任务CPU寄存器和程序计数器,再跳到新任务的程序计数器指的位置,运行新任务。
保存起来的CPU上下文会存储在系统内核中,等待任务重新调度。
保存CPU上下文和恢复CPU上下文是需要系统内核在CPU上运行才能完成的。
CPU上下文切换大体可以分为三种,进程上下文切换、线程上下文切换、中断上下文切换。
进程上下文切换
进程的上下文切换是指从一个进程切换到另一个进程运行。
liunx将进程的运行空间分为内核空间和用户空间。
内核空间具有最高等级,可以直接访问所有系统资源。
用户空间只能访问有限资源,不能直接访问内存等硬件设备,必须通过系统调用深入内核才能访问这些资源。
进程是由内核来管理和调度的,进程的切换只能发生在内核态。进程的上下文不仅包括了虚拟内存、栈、全局变量等用户空间的资源,还包括了内核堆栈、寄存器等内核空间的状态。
进程可以在这内核空间和用户空间运行,分别称为进程的用户态和进程的内核态。
从用户态到内核态的转变需要通过系统调用来完成,需要进行CPU上下文切换,保存用户态的CPU上下文,加载内核态的CPU上下文,结束后相反,其中发生了两次CPU上下文切换。这一切都在同一个进程中进行,会消耗系统资源,但并不是进程的CPU上下文切换。
进程的上下文切换比系统调用多一步,在保存当前进程的内核状态和CPU寄存器之前,需要先把该进程的虚拟内存和栈等保存下来,而加载了下一个进程的内核状态和CPU寄存器之后,还需要刷新下一个进程的虚拟内存和栈等。
进程上下文切换次数较多,很容易导致CPU将大量时间耗费在寄存器、内核栈以及虚拟内存等资源的保存和恢复上,大大缩短了真正运行进程的时间。导致平均负载升高。
线程的上下文切换
线程和进程的区别,线程是调度的基本单位,进程时资源拥有的基本单位,怎么理解呢?所谓内核中的任务调度,实际上调度的对象是线程,而进程时给线程提供虚拟内存、全局变量等资源的。
你也可以这样理解:
当进程只有一个线程时,可以认为进程就等于线程;
当进程拥有多个线程时,这些线程共享相同的虚拟内存和全局变量等资源,这些资源在上下文切换时并不需要修改。
当线程也有自己的私有数据时,比如自己的栈和寄存器,上下文切换时也需要保存。
根据上面描述的,线程的上下文切换就存在两种情况:
- 前后切换的两个线程是属于同一个进程,两个线程的资源基本是共享的,切换上下文时共享的资源不需要动,只有当线程有私有数据时,切换这些不共享的数据即可;
- 前后切换的两个进程不属于同一个进程,跟切换进程的上下文时一样的。
切换同一进程的线程比切换进程消耗更少的系统资源,这就是多线程对比多进程的优势。
中断上下文切换
中断处理拥有比进程更高的优先级
为了快速响应硬件的事件,中断处理会打断进程的正常调度和执行,转而执行中断处理程序,响应设备事件。在打断进程时,需要将当前进程的状态保存下来,中断结束后,再恢复到原有的状态。
中断上下文切换不涉及到进程的用户态。所以即便中断过程打断的是一个正在处于用户态的进程,也不需要保存和恢复这个进程的虚拟内存和全局变量等用户态资源。中断上下文只包括内核态中断服务程序执行所必须的状态,包括CPU寄存器、内存堆栈、硬件中断参数等。
一般中断程序都是短小的。力求尽快执行完成,但当发生过多的中断次数时,也可能带来严重的系统性能问题。
by kocor
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。