操作系统连载(2):内核态和用户态

  本篇作为操作系统学习连载的第2篇。

  内核态是操作系统代码执行时的状态,用户态是应用程序代码执行时的状态。无论是操作系统内核代码还是用户程序代码都是装入内存后执行的,即“取指-执行”,因此内核态代码和用户态代码在内存中存放的位置不同(一个门里一个门外)。放置内核态代码的一段内存区域是“内核态区域”,放置用户态代码的那段内存区域是“用户态区域”。建立系统调用这扇门的意图是让执行在用户态区域的代码不能进入内核态区域,具体来说,一是用户态代码不能通过 jmp 指令跳转到内核态内存区域中,二是用户态代码不能用 mov 指令取走存放在内核态内存中的数据。

  为什么?操作系统为内存区域设置了特权级(PL,privilege level)

  内存的使用由操作系统统一管理,操作系统在内存中划定一个区域,同时设置这个区域的特权级。操作系统将自己所在的内存区域的特权级设置的高,用户程序所在内存区域的特权级设置的低。用户程序执行时每访问一次内存都做一次审查。如果要访问的内存区域比自己的特权级高,CPU不执行。

  CPU设计了特权环的机制实现特权级检查,用硬件实现。CPU执行指令时发现需要进行特权级检查,就会取出两个值:当前特权级CPL 和描述符特权级DPL,进行比较,只有特权级满足要求,才允许这条指令被解释执行,否则出错。

  当前特权级(CPL)用来表示当前执行指令的特权级。CPL是存放在 CS 寄存器中的一个两位二级制数,00特权级最高,内核在这一层;11特权级最低,用户程序在这一层。想象一个环状结构,最内圈是内核态,最外圈是用户态。

  为什么 CPL 放在段寄存器中 CS 中?因为特权级描述的是一块内存区域,计算机中用来描述内存区域的概念是段(segment),段是由段寄存器表示的,当前指令由 CS:IP 指示,所以 CPL 就放在段寄存器中。

  描述符特权级(DPL)用来表示目标段的特权级。DPL 是存放在描述符表(GDT、IDT)中两位二进制数。特权级检查发生在访问/跳转到一个目标内存区域之时,操作系统中一块内存区域就是一个段,描述一个段的信息就放在对应的段表项中,即段描述符(descriptor)。

  举例:“jmpi 0,8”要跳转到 CS = 8 的目标代码段中,从 GDT 表中查找目标端的信息,根据查表得出的段描述符是 0x9A00,DPL是从左起的第2,3位,就是9,对应二进制 1001 中的中间2位:00,DPL = 00。CPL 是多少呢? CS = SETUPSEG = 0x9020,最后两位二进制数也是 00,这条指令可以执行。

ref: b站 李志军 操作系统

posted @ 2021-03-06 09:06  王晓天  阅读(275)  评论(0编辑  收藏  举报