最近在学习Linux内核,对于用户空间和内核空间、进程上下文与中断上下文有点混淆,在此好好整理一番。
一、CPU特权级别
CPU的所有指令中,有些指令是非常危险的,如果错用就会导致系统崩溃。所以,CPU将指令分为特权指令和非特权指令,不同的指令有不同的操作权限。于是便有了CPU的4个特权级别,ring0~ring3。ring0最高,ring3最低。Linux系统仅仅使用了ring0和ring3两个指令级别。
二、用户空间和内核空间
对于32位的操作系统而言,采用虚拟内存技术可以使寻址空间为4G(2^32),Linux操作系统将虚拟内存低3G的空间作为用户空间, 高1G的空间作为内核空间。也就是说只有在内核空间内,才会使用ring0级别的CPU指令。除此之外,操作系统的内核还可以完成进程调度 、内存管理等功能。每个进程可以通过系统调用(软中断)进入内核,因此,Linux内核由系统内的所有进程共享。从具体进程的角度来看,每个进程可以拥有4G字节的虚拟空间。空间分配如下图所示:
内核态与用户态:
(1)当一个任务(进程)执行系统调用而陷入内核代码中执行时,称进程处于内核运行态(内核态)。运行空间为内核空间。此时处理器处于特权级最高的(0级)内核代码中执行。当进程处于内核态时,执行的内核代码会使用当前进程的内核栈。每个进程都有自己的内核栈。
(2)当进程在执行用户自己的代码时,则称其处于用户运行态(用户态)。此时处理器在特权级最低的(3级)用户代码中运行。运行空间为用户空间。当正在执行用户程序而突然被中断程序中断时,此时用户程序也可以象征性地称为处于进程的内核态。因为中断处理程序将使用当前进程的内核栈。
三、进程上下文和中断上下文
所谓的上下文,简单来说就是寄存器值,各种参数变量和当时的环境(data 段地址,stack段地址等等);
程序在执行过程中通常有用户态和内核态两种状态,CPU对处于内核态根据上下文环境进一步细分,因此有了下面三种状态:
(1)内核态,内核运行于进程上下文状态,内核非中断服务程序进程运行于内核空间。
(2)内核态,内核运行于中断上下文状态,内核中断服务程序运行于内核空间。
(3)用户态,运行于用户空间。
前面我们讲过,用户空间的进程通过系统调用进入内核空间。实际上也是通过中断产生的。例如Linux的int 80h中断。当执行中断指令后,CPU内部机制将程序特权级别转到ring0层的特权级别。所以说,内核进程上下文是指用户空间通过系统调用进入内核空间,使用的内核栈、寄存器等资源。中断上下文则是指通过硬件中断调用内核中断处理程序,使用的内核栈、寄存器等资源。
LINUX完全注释中的一段话:
当一个进程在执行时,CPU的所有寄存器中的值、进程的状态以及堆栈中的内容被称为该进程的上下文。当内核需要切换到另一个进程时,它需要保存当前进程的所有状态,即保存当前进程的上下文,以便在再次执行该进程时,能够必得到切换时的状态执行下去。在LINUX中,当前进程上下文均保存在进程的任务数据结构中。在发生中断时,内核就在被中断进程的上下文中,在内核态下执行中断服务例程。但同时会保留所有需要用到的资源,以便中继服务结束时能恢复被中断进程的执行。