在 Linux 操作系统中,进程的运行空间被划分为内核空间和用户空间,这种划分是为了保护系统的稳定性和安全性。这两个空间对应着 CPU 的特权等级,分别为 Ring 0(内核态)和 Ring 3(用户态)。本文将深入介绍这两个空间的概念、特权等级的含义以及它们之间的切换机制。
内核空间是操作系统内核运行的区域,拥有最高的特权等级。在内核空间中,操作系统可以执行任意指令,访问所有硬件和内存资源。这包括对系统硬件、设备驱动程序和核心数据结构的完全访问。内核空间通常包含了操作系统的内核代码和数据结构。
用户空间是供用户程序执行的区域,拥有较低的特权等级。在用户空间中,程序只能执行受限的指令,且对硬件资源的直接访问受到限制。用户空间包含了用户应用程序的代码和数据,以及一些共享库和用户环境的运行时信息。
CPU 特权等级用于区分不同程序对计算机系统资源的访问权限。在 x86 架构中,特权等级被分为四个环,分别是 Ring 0 到 Ring 3。Ring 0 拥有最高特权,而 Ring 3 拥有最低特权。
cke_17455.png
cke_17455.png
Ring 0 是最高特权等级,对应内核空间。在 Ring 0 中,操作系统内核运行,可以执行任意指令,访问系统的全部资源。内核态下运行的代码可以执行特权指令,例如修改全局描述符表(GDT)和局部描述符表(LDT),以及执行 I/O 操作。
Ring 3 是最低特权等级,对应用户空间。在 Ring 3 中,运行用户应用程序,程序只能执行非特权指令,访问受限资源。用户态下运行的代码无法直接执行一些特权指令,例如修改 GDT 和 LDT。必须通过系统调用陷入到内核中,才能访问这些特权资源。
Linux 是一个多任务操作系统,支持远远大于cpu数量的任务并行运行,但是从底层上看其实这些任务也不是同时运行,而是操作系统在非常短的时间内把CPU轮流分配给这些任务,这样在表象看起来像是多任务同时运行一样。
因为这些任务实际上是轮流使用cpu,所以在任务运行之前就得有地方记录这些任务的运行信息(需要加载什么信息,在哪里开始运行等)--CPU 寄存器和程序计数器。
在 Linux 操作系统中,当操作系统进行进程上下文切换时,通常会保存和恢复CPU 寄存器的状态,以及程序计数器的值。这确保了在切换回进程时,它能够继续执行先前被中断的位置。这是操作系统实现多任务和多进程并发执行的基本机制之一。
CPU 寄存器:
程序计数器(Program Counter,PC):
CPU 寄存器和程序计数器。都是 CPU 在运行任何任务前,必须的依赖环境,因此也被叫做 CPU 上下文。
一句话总结上下文:
在每个任务运行前,cpu需要知道任务是从哪儿运行的,然后从哪儿开始的,也就是说,需要系统给它设置好 CPU寄存器和程序计数器, cpu的寄存器是,cpu内置的容量小,但是速度极快的内存,而程序计数器,则是用来存储正在执行的指令位置,或者即将执行的吓一跳指令位置。他们是cpu在运行任何任务前,都必须依赖的环境(包括寄存器状态、内存映射、打开的文件、进程优先级等),因此也被叫做CPU上下文
一句话总结上下文切换:
就是先把前一个任务的 CPU 上下文(也就是 CPU 寄存器和程序计数器)保存起来,然后加载新任务的上下文到这些寄存器和程序计数器,最后再跳转到程序计数器所指的新位置,运行新任务。
上下文切换是指操作系统在多任务环境下,从一个任务切换到另一个任务时保存和恢复这些上下文信息的过程。在 Linux 系统中,上下文和上下文切换是操作系统中关键的概念,对于系统性能和多任务处理有着重要的影响。
在多任务操作系统中,CPU 上下文切换是实现并发执行的关键机制。根据任务的不同,可以把上下文切换可以分成三种不同的上下文切换场景:进程上下文切换、线程上下文切换以及中断上下文切换。我们将从底层原理出发,详细介绍每种场景的具体实现和影响因素。
进程上下文切换是指从一个进程切换到另一个进程。它发生在多任务系统中,由调度器负责决定哪个进程获得 CPU 时间。上下文切换的开销包括保存当前进程的上下文、加载新进程的上下文以及刷新内存映射等。
在一开始介绍进程的运行空间与系统等级的时候,进程在从用户态到内核态的转变涉及系统调用,这里的系统调用也涉及上下文切换。系统调用是用户程序请求内核执行特权操作的方式,例如打开、读取或关闭文件。当进行文件内容查看等操作时,需要多次系统调用完成。每次系统调用都引发了 CPU 上下文的切换。
具体过程如下:
一次系统调用的过程实际上发生了两次 CPU 上下文切换。
虽然系统调用过程中不涉及虚拟内存等用户态资源的切换,也不会切换进程,但实际上,CPU 的上下文切换是无法避免的。因此,系统调用过程中的上下文切换通常被称为特权模式切换,而非上下文切换。
进程上下文切换与系统调用有明显区别:
上下文切换的过程并非“免费”,它需要内核在 CPU 上运行来完成。根据Tsuna的实验数据,每次上下文切换都需要几十纳秒到数微秒的 CPU 时间。在进程上下文切换次数较多的情况下,容易导致 CPU 时间主要花费在资源的保存和恢复上,而非真正的进程执行。
在 Linux 系统中,进程的调度并不仅仅发生在进程执行完终止的时候。我们来逐一梳理几个触发进程调度的场景,以加深对进程调度机制的理解。
当前运行进程的时间片耗尽。
为了保证所有进程能够得到公平调度,CPU 时间被划分为一段段的时间片,这些时间片轮流分配给各个进程。当某个进程的时间片耗尽时,系统会挂起该进程,并切换到等待 CPU 的其他进程运行。
进程等待某些系统资源(如内存)。
在系统资源不足的情况下(例如内存不足),进程需要等待资源满足才能继续运行。此时,该进程会被挂起,并由系统调度其他等待 CPU 的进程运行。
进程主动调用睡眠函数(如 sleep)。
通过睡眠函数(如 sleep)等方式,进程可以主动挂起自己,等待一定的时间后再次被调度运行。
高优先级进程就绪并准备运行。
当有优先级更高的进程就绪时,为了确保高优先级进程能够及时运行,当前进程会被挂起,系统调度高优先级进程运行。
硬件设备产生中断。
发生硬件中断时,CPU 上正在执行的进程会被中断挂起,转而执行内核中的中断服务程序。一旦中断处理完毕,原先的进程可能会被重新调度运行。
线程上下文切换与进程上下文切换类似,但开销更小。因为线程共享相同的地址空间,切换时无需刷新内存映射。线程上下文切换通常发生在同一进程内的不同线程之间。
线程(Thread)和进程(Process)是操作系统中用于执行程序的两个基本概念,在开始分析之前,我们先了解下线程与进程:线程是调度的基本单位,而进程则是资源拥有的基本单位
线程上下文切换 可以分为两种情况
中断上下文切换是由硬件中断或软件中断触发的。当中断发生时,操作系统会保存当前进程或线程的上下文,然后转入中断服务例程执行。执行完中断服务例程后,操作系统会恢复之前保存的上下文,继续执行被中断的进程或线程。
中断上下文切换与进程上下文切换有着明显的区别。中断上下文切换并不涉及到进程的用户态,因此在中断过程中打断了一个正处在用户态的进程时,不需要保存和恢复这个进程的虚拟内存、全局变量等用户态资源。相比之下,中断上下文只包括内核态中断服务程序执行所必需的状态,主要包括 CPU 寄存器、内核堆栈、硬件中断参数等。
中断上下文切换的特点:
中断上下文切换的设计目标是最小化对系统性能的影响,专注于提供必要的执行环境以迅速处理硬件中断。这种机制使得操作系统能够高效地响应外部事件,保证系统的可靠性和实时性。
上下文和上下文切换是操作系统中的关键概念,直接影响系统的性能和响应能力。了解上下文的概念以及上下文切换的过程有助于理解操作系统的工作原理,并能够优化程序以提高系统的性能和效率。在设计和开发多任务应用程序时,合理处理上下文切换是至关重要的。
复制
将client_name.ovpn传至手机后,在openvpn中打开文件即可链接
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。