CPU的两种工作状态:内核态和用户态(或者称管态和目态)

谈到CPU的这两个工作状态,也就是处理器的这两个工作状态,那我们有必要说一下为什么搞出这两个鬼玩意出来。
             用过电脑的娃娃们肯定知道在一个系统中既有操作系统的程序,也由普通用户的程序。但那么多指令,可不是随便乱用的,有些指令只能由系统来使用,禁止用户程序去直接访问。为了保证操作系统和各个应用程序能够顺利运行,就必须对他们进行限制,否则的话就根本没有办法保证系统的安全性和稳定。
             所以呢,根据运行程序对资源和机器指令的使用权限,把处理器设置为不同的状态。多数系统把处理器的工作状态分为管态和目态两种。也就是我们今天要说的这两个东西。
             所谓管态,即操作系统的管理程序运行时的状态,它具有较高的特权级别,也称为特权态、系统态、内核态或者核心态。当处理器处于管态时,他可以执行所有的指令,包括各种特权指令,也可以使用所有的资源,并且具有改变处理器状态的能力,是感觉很牛逼。需要指出的是,管态和超级用户不同,前者是指CPU的状态,后者是指一种特殊的计算机用户;前者主要是从硬件的角度去执行任何指令,而后者是从软件的角度来管理系统的软硬件资源,如用户账户、权限管理、文件访问等。超级用户执行的程序不一定运行在管态,而管态程序也不一定由系统管理员启动,普通用户也可以启动。
             所谓目态,即用户程序运行时的状态,它具有较低的特权级别,又称为普通态或用户态。在这种状态下不能使用特权指令,不能直接使用系统资源,也不能改变CPU的工作状态,并且只能访问这个用户程序自己的存储空间。用户态不允许程序进行处理器中要求特权态的操作,以避免操作系统崩溃。每个进程都在各自的用户空间 中运行,而不允许存取其他程序的用户空间。
                 百度百科上的这个图片对于这两个状态划分就挺好的。
CPU的两种工作状态:内核态和用户态(或者称管态和目态)
           当一个任务(进程)执行系统调用而陷入内核代码中执行时,我们就称进程处于内核运行态(或简称为内核态)。此时处理器处于特权级最高的(0级)内核 代码中执行。当进程处于内核态时,执行的内核代码会使用当前进程的内核栈。每个进程都有自己的内核栈。当进程在执行用户自己的代码时,则称其处于用户运行 态(用户态)。即此时处理器在特权级最低的(3级)用户代码中运行。
             在内核态下CPU可执行任何指令,在用户态下CPU只能执行非特权指令。当CPU处于内核态,可以随意进入用户态;而当CPU处于用户态时,用 户从用户态切换到内核态只有在系统调用和中断两种情况下发生,一般程序一开始都是运行于用户态,当程序需要使用系统资源时,就必须通过调用软中断进入内核 态。   
             Linux使用了Ring3级别运行用户态,Ring0作为内核态,没有使用Ring1和Ring2。Ring3状态不能访问Ring0的地址 空间,包括代码和数据。Linux进程的4GB地址空间,3G-4G部分大家是共享的,是内核态的地址空间,这里存放在整个内核的代码和所有的内核模块, 以及内核所维护的数据。用户运行一个程序,该程序所创建的进程开始是运行在用户态的,如果要执行文件操作,网络数据发送等操作,必须通过 write,send等系统调用,这些系统调用会调用内核中的代码来完成操作,这时,必须切换到Ring0,然后进入3GB-4GB中的内核地址空间去执 行这些代码完成操作,完成后,切换回Ring3,回到用户态。这样,用户态的程序就不能随意操作内核地址空间,具有一定的安全保护作用。
             我在网易的一篇博客中看到一个解释挺好的一个文章,对方是从一段实例中开始的,所以我粘贴过来分享了一下:

1. 用户态和内核态的概念区别

究竟什么是用户态,什么是内核态,这两个基本概念以前一直理解得不是很清楚,根本原因个人觉得是在于因为大部分时候我们在写程序时关注的重点和着眼的角度放在了实现的功能和代码的逻辑性上,先看一个例子:

1)例子

C代码
  1. void testfork(){  
  2. if(0 fork()){  
  3. printf(“create new process success!\n”);  
  4.  
  5. printf(“testfork ok\n”);  
  6.  
 

这 段代码很简单,从功能的角度来看,就是实际执行了一个fork(),生成一个 新的进程,从逻辑的角度看,就是判断了如果fork()返回的是0则打印相关语句,然后函数最后再打印一句表示执行完整个testfork()函数。代码 的执行逻辑和功能上看就是如此简单,一共四行代码,从上到下一句一句执行而已,完全看不出来哪里有体现出用户态和进程态的概念。

如果说前面两种是静态观察的角度看的话,我们还可以从动态的角度来看这段代码,即它被转换成CPU执行的指令后加载执行的过程,这时这段程序就是一个动态执行的指令序列。而究竟加载了哪些代码,如何加载就是和操作系统密切相关了。

2)特权级

熟 悉Unix/Linux系统的人都知道,fork的工作实际上是以系统调用的 方式完成相应功能的,具体的工作是由sys_fork负责实施。其实无论是不是Unix或者Linux,对于任何操作系统来说,创建一个新的进程都是属于 核心功能,因为它要做很多底层细致地工作,消耗系统的物理资源,比如分配物理内存,从父进程拷贝相关信息,拷贝设置页目录页表等等,这些显然不能随便让哪 个程序就能去做,于是就自然引出特权级别的概念,显然,最关键性的权力必须由高特权级的程序来执行,这样才可以做到集中管理,减少有限资源的访问和使用冲 突。

特权级显然是非常有效的管理和控制程序执行的手 段,因此在硬件上对特权级做了很 多支持,就Intel x86架构的CPU来说一共有0~3四个特权级,0级最高,3级最低,硬件上在执行每条指令时都会对指令所具有的特权级做相应的检查,相关的概念有 CPL、DPL和RPL,这里不再过多阐述。硬件已经提供了一套特权级使用的相关机制,软件自然就是好好利用的问题,这属于操作系统要做的事情,对于 Unix/Linux来说,只使用了0级特权级和3级特权级。也就是说在Unix/Linux系统中,一条工作在0级特权级的指令具有了CPU能提供的最 高权力,而一条工作在3级特权级的指令具有CPU提供的最低或者说最基本权力。

3)用户态和内核态

现 在我们从特权级的调度来理解用户态和内核态就比较好理解了,当程序运行在3级 特权级上时,就可以称之为运行在用户态,因为这是最低特权级,是普通的用户进程运行的特权级,大部分用户直接面对的程序都是运行在用户态;反之,当程序运 行在0级特权级上时,就可以称之为运行在内核态。

虽 然用户态下和内核态下工作的程序有很多差别,但最重要的差别就在于特权级的不 同,即权力的不同。运行在用户态下的程序不能直接访问操作系统内核数据结构和程序,比如上面例子中的testfork()就不能直接调用 sys_fork(),因为前者是工作在用户态,属于用户态程序,而sys_fork()是工作在内核态,属于内核态程序。

当 我们在系统中执行一个程序时,大部分时间是运行在用户态下的,在其需要操作系 统帮助完成某些它没有权力和能力完成的工作时就会切换到内核态,比如testfork()最初运行在用户态进程下,当它调用fork()最终触发 sys_fork()的执行时,就切换到了内核态。

2. 用户态和内核态的转换

1)用户态切换到内核态的3种方式

a. 系统调用

这 是用户态进程主动要求切换到内核态的一种方式,用户态进程通过系统调用申请使 用操作系统提供的服务程序完成工作,比如前例中fork()实际上就是执行了一个创建新进程的系统调用。而系统调用的机制其核心还是使用了操作系统为用户 特别开放的一个中断来实现,例如Linux的int 80h中断。

b. 异常

当CPU在执行运行在用户态下的程序时,发生了某些事先不可知的异常,这时会触发由当前运行进程切换到处理此异常的内核相关程序中,也就转到了内核态,比如缺页异常。

c. 外围设备的中断

当 外围设备完成用户请求的操作后,会向CPU发出相应的中断信号,这时CPU会 暂停执行下一条即将要执行的指令转而去执行与中断信号对应的处理程序,如果先前执行的指令是用户态下的程序,那么这个转换的过程自然也就发生了由用户态到 内核态的切换。比如硬盘读写操作完成,系统会切换到硬盘读写的中断处理程序中执行后续操作等。

这3种方式是系统在运行时由用户态转到内核态的最主要方式,其中系统调用可以认为是用户进程主动发起的,异常和外围设备中断则是被动的。

2)具体的切换操作

从 触发方式上看,可以认为存在前述3种不同的类型,但是从最终实际完成由用户态 到内核态的切换操作上来说,涉及的关键步骤是完全一致的,没有任何区别,都相当于执行了一个中断响应的过程,因为系统调用实际上最终是中断机制实现的,而 异常和中断的处理机制基本上也是一致的,关于它们的具体区别这里不再赘述。关于中断处理机制的细节和步骤这里也不做过多分析,涉及到由用户态切换到内核态 的步骤主要包括:

[1] 从当前进程的描述符中提取其内核栈的ss0及esp0信息。

[2] 使用ss0和esp0指向的内核栈将当前进程的cs,eip,eflags,ss,esp信息保存起来,这个

过程也完成了由用户栈到内核栈的切换过程,同时保存了被暂停执行的程序的下一

条指令。

[3] 将先前由中断向量检索得到的中断处理程序的cs,eip信息装入相应的寄存器,开始

执行中断处理程序,这时就转到了内核态的程序执行了。

  • 8
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1. 硬件将处理机划分为两种状态,即管目态,这样做给操作系统设计带来什么好处 ? 答:便于设计安全可靠的操作系统。管目态是计算机硬件为保护操作系统免受用户程序的干扰和破坏而引入的两种状态。通常操作系统在管下运行,可以执行所有机器指令;而用户程序在目态下运行,只能执行非特权指令。如果用户程序企图在目态下执行特权指令,将会引起保护性中断,由操作系统终止该程序的执行,从而保护了操作系统。 2. 何为特权指令?举例说明之。如果允许用户执行特权指令,会带来什么后果? 答:只能在管下才能执行的指令称为特权指令。如开关中断、置程序状态寄存器等。如果允许用户执行特权指令,它将不仅影响当前运行的程序,而且还有可能影响操作系统的正常运行,甚至整个系统。3. 中断向量在机器中的存储位置是由硬件确定的,还是由软件确定的 ? 答:中断向量在机器中的位置是由硬件确定的。例如,在 INTEL 80x86 CPU 中,内存空间0x00000——0x003ff为中断向量空间。4. 中断向量的内容是由操作系统程序确定的还是由用户程序确定的? 答:中断向量的内容是由操作系统程序确定的。向量的内容包括中断处理程序的入口地址和程序状态字(中断处理程序运行环境),中断处理程序是由操作系统装入内存的,操作系统将根据装入的实际地址和该中断处理程序的运行环境来填写中断向量。5. 中断向量内的处理机状态位应当标明是管还是目态 ? 为什么? 答:应当标明是管。 该状态由系统初试化程序设置,这样才能保证中断发生后进入操作系统规定的中断处理程序。 6. 中断和程序并发之间的关系是什么? 答:中断是程序并发的必要条件。如果没有中断,操作系统不能获得系统控制权,无法按调度算法对处机进行重新分配,一个程序将一直运行到结束而不会被打断。7. 说明“栈”和“堆”的差别. 答:栈是一块按后进先出(FIFO)规则访问的存储区域,用来实现中断嵌套和子程序调用的参数和返回断点。而堆虽然是一块存储区域,但是对堆的访问是任意的,没有后进先出的要求,堆主要用来为动变量分配存储空间。 8. 何为系统栈?何为用户栈?系统栈有何用途?用户栈有何用途? 答:系统栈是内存中操作系统空间的一个固定区域;用户栈是内存中用户空间的一个区域。系统栈的作用:(1)保存中断现场,对于嵌套中断,被中断程序的现场信息依次压入系统栈,中断返回时逆序弹出;(2)保存操作系统子程序间相互调用的参数、返回值、返回点、以及子程序的局部变量。用户栈的作用:用于保存用户进程的子程序间相互调用的参数、返回值、返回点、以及子程序的局部变量。9. 用户堆栈段的长度为何无法确定 ? 答:用户堆栈段的长度主要取决于两个因素:(1)用户进程(线程)中子程序(函数)之间的嵌套调用深度;(2)子程序参数和局部变量的数量及类型;(3)动变量的使用。这些在进程(线程)运行前无法确定,由此导致用户堆栈段的长度无法预先准确确定。 10堆栈段的动扩充为何可能导致进程空间的搬迁? 答:堆栈段的扩充需要在原来进程空间大小的基础上增添新的存储区域,而且通常要求与原来存储区域连续。由于原存放位置处可扩展的区域可能已经被其它进程占用,故可能需要将整个进程空间搬迁到另外一个区域,以实现地址空间扩展要求。11. 何谓并行 ? 何谓并发? 在单处理机系统中,下述并行和并发现象哪些可能发生,哪些不会发生 ? (1) 进程与进程之间的并行; (2) 进程与进程之间的并发; (3) 处理机与设备之间的并行; (4) 处理机与通道之间的并行; (5) 通道与通道之间的并行; (6) 设备与设备之间的并行; 答:所谓并行是指同一时刻同时进行,进程并行需要多处理器的支持;所谓并发,是指在一段时间内,多个进程都在向前推进,而在同一时刻,可能只有一个进程在执行,多个进程轮流使用处理器。 在单处理器传统中,可能发生的并行和并发现象如下: (2) 进程与进程之间的并发。例如,在Windows操作系统中,mp3播放进程和Word字处理进程可以并发执行,这样用户就可以边听音乐边写文章了。 (3) 处理机与设备之间的并行。例如,当处理机进行科学运算时,打印机可以打印文档。 (4) 处理机与通道之间的并行。通道程序的执行可与处理机的操作并行。 (5) 通道与通道之间的并行。通常一个系统中有多个通道,这些通道可以并行地执行相应的通道程序。 (6) 设备与设备之间的并行。例如打印机打印文档时,磁带机在输入数据。 12. 何谓作业? 它包括哪几个部分? 各部分用途是什么?答:所谓作业是指用户要求计算机系统为其完成的计算任务的集合。一个作业通常包括程序、程序所处理的数据以及作业说明书。程序用来完成特定的功能,数据是程序处理的对象,作业说明书用来说明作业处理的步骤。13. 从透明性和资源共享两方面,说明网络操作系统与分布式操作系统之间的差别。 答:从透明性上看,分布式操作系统优于网络操作系统。网络用户能够感觉到所访问的资源是在本地还是在远地;而在分布式系统中,用户感觉不到所访问的资源是否在本地,分布式操作系统掩盖了资源在地理位置上的差异。 从资源共享上看 ,分布式操作系统比网络操作系统能共享更多的资源。在网络操作系统中,一个计算任务不能由一台主机任意迁移到另外一台主机上运行;而在分布式操作系统中,所有作业可以由一台主机任意迁移到另外一台主机上处理,即可实现处理机资源的共享,从而达到整个系统的负载平衡。 14. 为什么构成分布式系统的主机一般都是相同的或兼容的?答:这样更有利于进程的动迁移。如果主机不兼容,则在一台主机上能运行的进程,因所用指令系统不同,在另一台主机上可能无法运行,导致进程难于在不同主机间迁移,使得分布式系统难于实现负载平衡。构成分布式系统的主机一般都是相同的或兼容的。15. 为什么嵌入式操作系统通常采用微内核结构?   答:嵌入式操作系统与一般操作系统相比具有比较明显的差别 : (1)嵌入式操作系统规模一般较小,因为一般硬件配置较低,而且对操作系统提供的功能要求也不高。(2)应用领域差别大,对于不同的应用领域其硬件环境和设备配置情况有明显差别。 所以,嵌入式操作系统一般采用微内核 ( micro kernel )结构,包括如下基本功能: (1)处理机调度;(2)基本内存管理;(3)通讯机制;(4)电源管理。在这些基本成分之上可进行扩展,以适应不同应用目标。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值