本文内容较为浅显,主要为了简单介绍用户态和内核态的区别。
让我们对内核态和用户态进行简要的概述。在计算机操作系统中,当我们执行某些操作,如应用程序从磁盘读取数据时,并不会直接将数据从磁盘加载到应用内存中,而是会经历一系列的中间步骤。
- 数据会从“磁盘”复制到“内核Buffer”。
- 然后,数据再从“内核Buffer”复制到“用户Buffer”。
上述过程便涉及到了用户态和内核态的概念。简单来说,这两种“态”是操作系统的运行级别。
当我们编写的程序运行时,最终会被编译或解释成一系列的CPU指令供CPU执行。无论是用户态还是内核态,这些指令都由CPU执行。我们可以说,这两种态实际上代表了当前CPU的状态。
为何要区分这两种态呢?这是因为CPU指令根据其重要性有不同级别的权限。一些指令执行失败可能只是小问题,而有些则可能导致整个操作系统崩溃,甚至需要重启系统。如果随意让应用程序执行这些指令,将大大增加系统崩溃的风险。
CPU指令的权限在许多架构中都有所划分。以Intel X86为例,它将CPU指令权限分为四个等级。这些等级的权限高低程度可以通过特定的图表来识别。
在Linux系统中,由于只有Ring0和Ring3级别的指令,因此我们可以对用户态和内核态进行更详细的描述:执行Ring0级别指令的为内核态,执行Ring3级别指令的为用户态。
理解了指令限的概念后,我们可以重新阐述一下:态实际上代表了CPU正在执行什么级别的指令。
了解用户态和内核态的区别以及为何要区分它们后,我们来看一下何时会从用户态切换到内核态。答案是在发生系统调用的时候。
那么,什么是系统调用呢?当用户态的程序需要向操作系统请求更高权限的服务时,它会通过系统调用向内核发起请求。而为了方便开发和管理,操作系统会提供许多接口供程序调用,如申请动态内存空间等。
为了简化内部复杂的管理工作,开发者会使用库函数来调用内核提供的接口。当库函数发起系统调用时,用户态便会切换为内核态去执行相应的内核方法。
除了系统调用之外,还有两种情况会导致态的切换:发生异常和中断。