操作系统用户态和内核态之间的切换过程

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

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

1)例子

void testfork(){

if(0 = = fork()){

printf(“create new process success!/n”);

}

printf(“testfork ok/n”);

}

这段代码很简单,从功能的角度来看,就是实际执行了一个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信息装入相应的寄存器,开始

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

举个例子:

下面的图中执行了连续的两条指令: mov eax, 0x4

int 0x80

可以看到,指令mov eax, 0x4对应的cs为0x7,eip为0x308a,ss为0xf,esp为0x80320

这表明此条指令的特权级是3级,也就是说该指令是工作在用户态下的。

int 0x80即所谓的系统调用执行的软中断,此条指令执行完之后,cs变换成了0x8,eip为0x1400,ss变成了0x10, esp 变成了0x1ffffec。这时系统已经转入了内核态执行,而且栈也变为了内核栈。

内核态程序执行完毕时如果要从内核态返回用户态,可以通过执行指令iret来完成,指令iret会将先前压栈的进入内核态前的cs,eip,eflags,ss,esp信息从栈里弹出,加载到各个对应的寄存器中,重新开始执行用户态的程序,这个过程不再详述。

操作系统用户态和内核态之间的切换过程相关推荐

  1. 操作系统(概述、组成)、用户态、内核态

    1. 概述 1.1 基本特征 1.1.1 并发 并发是指宏观上在一段时间内能同时运行多个程序,而并行则指同一时刻能运行多个指令. 并行需要硬件支持,如多流水线或者多处理器. 操作系统通过引入进程和线程 ...

  2. 操作系统 | 用户态和内核态的切换(中断、系统调用与过程(库函数)调用)

    文章目录 中断 过程调用 系统调用 过程调用和系统调用的区别 中断 用户态.内核态之间的切换是怎么实现的? 用户态→内核态 是通过中断实现的.并且 中断是唯一途径 . 核心态→用户态 的切换是通过执行 ...

  3. 操作系统基础知识用户态和内核态的区别

    这节课给你带来了一道非常经典的面试题目:用户态线程和内核态线程有什么区别? 这是一个组合型的问题,由很多小问题组装而成,比如: 用户态和内核态是什么? 用户级线程和内核级线程是一个怎样的对应关系? 内 ...

  4. 操作系统:用户态与内核态

    文章目录 用户态与内核态 用户态与内核态的概念 用户态 内核态 为什么要区分内核态和用户态 用户态与内核态的区别 用户态切换到内核态的方式 用户态与内核态空间分配 用户态与内核态 用户态与内核态的概念 ...

  5. 用户态和内核态之间的切换

    用户态和内核态之间的切换 切换方式 从用户态到内核态切换可以通过三种方式,或者说会导致从用户态切换到内核态的操作: 系统调用,这个上面已经讲解过了,在我公众号之前的文章也有讲解过.其实系统调用本身就是 ...

  6. 操作系统~用户态进入内核态的方式(中断、异常、系统调用)

    中断与异常 中断的概念和作用 当中断发生时,CPU立即进入核心态 当中断发生后,当前运行的进程暂停运行,并由操作系统内核对中断进行处理 对于不同的中断信号,会进行不同的处理 发生了中断,就意味着需要操 ...

  7. 操作系统用户态和内核态

    用户态和内核态 一. 用户态和内核态的概念? 二.为什么需要用户态和内核态? 三.用户态与内核态的切换? 四.用户态和内核态的详细介绍? 一. 用户态和内核态的概念? 内核态: CPU可以访问内存所有 ...

  8. 用户态与内核态之间切换详解

    用户空间和内核空间 用户程序有用户态和内核态两种状态.用户态就是执行在用户空间中,不能直接执行系统调用.必须先切换到内核态,也就是系统调用的相关数据信息必须存储在内核空间中,然后执行系统调用. 操作硬 ...

  9. Java程序员需要掌握的计算机底层知识(二):操作系统、内核、用户态与内核态、系统调用的执行过程

    操作系统 启动过程 通电 -> bios uefi 工作 -> 自检 -> 到硬盘固定位置加载bootloader -> 读取可配置信息 -> CMOS CMOS 用来存 ...

最新文章

  1. 图像处理工具包ImagXpress的多页TIFF编辑API的使用(1)
  2. -lt -gt -ge -le -eq的意义
  3. 理解nodejs中函数的参数的来由
  4. 一文带你全面了解电商在线支付
  5. SuperMap.IS.AjaxScript缓冲区分析及专题图制作
  6. [Win32]一个调试器的实现(四)读取寄存器和内存
  7. 手机qq2008触屏版_[进行中]数码手机周年庆
  8. Nhibernate教程2(3)
  9. Java 之 JavaScript (一)
  10. win8卸载mysql数据库,彻底卸载win8自带的metro应用的方法
  11. cd如何省略空格 linux_在 Linux 上调整命令历史 | Linux 中国
  12. 【反编译】apk反编译之修改贴吧发贴回帖时显示的地理位置
  13. 使用FFmpeg工具进行推流、拉流、截图、变速、转换,及常见问题处理
  14. 耳机及音响--煲机软件
  15. 前端工程中使用iconfont图标
  16. 计算机网络实验二 VLAN间路由
  17. HBase-14.1-JMX监控实战-hadoop
  18. Swift iOS macOS 如何 Localize StoryBoard,StoryBoard 本地化,添加多语言支持,基于 String
  19. Numpy || np.arange()、np.linspace()、np.logspace()、np.zeros()、np.ones()函数用法指南
  20. STL--String类的常用功能复写

热门文章

  1. STM32笔记:STM32F407的TIM1和TIM2同步配置
  2. 中科软深圳分公司面试题
  3. C++ const修饰函数、函数参数、函数返回值 浅析
  4. 整理了Android面中常见的62个Java知识点...
  5. 下午一口气睡了五个小时
  6. 使用opencv进行Ostu二值化
  7. Zookeeper--Watcher数据变更的通知
  8. AC日记——逃出克隆岛 (bfs)
  9. git 删除本地所有未提交的更改
  10. linux中DNS+apache服务器配置