【操作系统】一篇文章带你快速搞懂用户态和内核态

这篇具有很好参考价值的文章主要介绍了【操作系统】一篇文章带你快速搞懂用户态和内核态。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

一、指令划分

二、特权级别

三、操作系统需要两种CPU状态

四、CPU状态之间的转换

4.1 CPU状态转换的途径

4.2 CPU状态转化流程

4.3 什么情况会导致用户态到内核态切换

通常来说,以下三种情况会导致用户态到内核态的切换

1、系统调用

2、异常

3、外围设备的中断

五、为什么要有用户态和内核态

六、内核态与用户态的区别


一、指令划分

在说用户态与内核态之前,有必要说一下 CPU指令集,指令集是 CPU 实现软件指挥硬件执行的媒介,具体来说每一条汇编语句都对应了一条CPU指令,而非常非常多的 CPU指令 在一起,可以组成一个、甚至多个集合,指令的集合叫CPU指令集

同时 CPU指令集 有权限分级,大家试想,CPU指令集 可以直接操作硬件的,要是因为指令操作的不规范,造成的错误会影响整个计算机系统的。好比你写程序,因为对硬件操作不熟悉,导致操作系统内核、及其他所有正在运行的程序,都可能会因为操作失误而受到不可挽回的错误,最后只能重启计算机才行。

而对于硬件的操作是非常复杂的,参数众多,出问题的几率相当大,必须谨慎的进行操作,对开发人员来说是个艰巨的任务,还会增加负担,同时开发人员在这方面也不被信任,所以操作系统内核直接屏蔽开发人员对硬件操作的可能,都不让你碰到这些CPU指令集。

所以CPU指令可以分为如下两大类:

  • 特权指令:只能由操作系统使用、用户程序不能使用的指令。 举例:启动I/O 内存清零 修改程序状态字 设置时钟 允许/禁止终端 停机
  • 非特权指令:用户程序可以使用的指令。 举例:控制转移 算数运算 取数指令 访管指令(使用户程序从用户态陷入内核态)

核心态与用户态,操作系统,# Linux,操作系统,用户态,内核态,Linux,多线程

上图就生动的展示了CPU指令的权限限制,开发人员只能通过操作系统来完成一些指令集的调用。

我们可以用一个小故事形象生动的描述它们之间的关系:

张三是某科技公司的初级Java开发工程师(低权限),目前在15楼办公码代码,公司提供的资源仅有一套电脑(用户态),张三想着这一线的房价,倍感压力山大,于是给自己定下一个目标,一定要做技术总监,在一线扎根。

奋斗逼张三,奋斗5年终于当上了技术总监(高权限),之后张三搬到30楼,可以随时向资源部(系统调用)申请公司各种资源与获取公司的机密信息(内核态),所谓是走上人生巅峰。

通过这个故事,我们发现,低权限的资源范围较小,高权限的资源范围更大,所谓的「用户态与内核态只是不同权限的资源范围」

二、特权级别

针对上一节讲的现实需求,硬件设备商直接提供硬件级别的支持,做法就是对 C P U 指令集设置了权限,不同级别权限能使用的 CPU 指令集 是有限的,以 Inter CPU 为例,Inter把 CPU指令集 操作的权限由高到低划为4级:

  • ring 0
  • ring 1
  • ring 2
  • ring 3

其中 ring 0 权限最高,可以使用所有 CPU 指令集,相当于内核态;ring 3 权限最低,仅能使用常规 CPU指令集,不能使用操作硬件资源的 CPU指令集,比如 I O 读写、网卡访问、申请内存都不行,R3相当于用户态;Linux系统仅采用ring 0 和 ring 3 这2个权限。

核心态与用户态,操作系统,# Linux,操作系统,用户态,内核态,Linux,多线程

执行内核空间的代码,具有ring 0保护级别,有对硬件的所有操作权限,可以执行所有CPU指令集,访问任意地址的内存,在内核模式下的任何异常都是灾难性的,将会导致整台机器停机。

在用户模式下,具有ring 3保护级别,代码没有对硬件的直接控制权限,也不能直接访问地址的内存,程序是通过调用系统接口(System Call APIs)来达到访问硬件和内存,在这种保护模式下,即时程序发生崩溃也是可以恢复的,在电脑上大部分程序都是在,用户模式下运行的。

简单点说:

  • ring 0被叫做内核态,完全在操作系统内核中运行
  • ring 3被叫做用户态,在应用程序中运行

三、操作系统需要两种CPU状态

用户态和内核态是操作系统的两种运行状态:

  • 内核态(Kernel Mode):处于内核态的 CPU 可以访问任意的数据,包括外围设备,比如网卡、硬盘等,处于内核态的 CPU 可以从一个程序切换到另外一个程序,并且该状态下占用 CPU 不会发生被抢占情况,一般处于特权级 0 的状态我们称之为内核态。该状态下用来运行操作系统程序,操作硬件。
  • 用户态(User Mode):处于用户态的 CPU 只能受限的访问内存,并且不允许访问外围设备,用户态下的 CPU 不允许独占,也就是说 CPU 能够被其他程序获取。该状态下用来运行用户程序。

操作系统的内核态和用户态不光限制了CPU指令集的调用权限,在内存资源的使用上,操作系统也对用户态与内核态也做了限制,每个进程创建都会分配「虚拟空间地址」,以Linux32位操作系统为例,它的寻址空间范围是 4G(2的32次方),而操作系统会把虚拟控制地址划分为两部分,一部分为内核空间,另一部分为用户空间高位的 1G(从虚拟地址 0xC0000000 到 0xFFFFFFFF)由内核使用,而低位的 3G(从虚拟地址 0x00000000 到 0xBFFFFFFF)由各个进程使用

核心态与用户态,操作系统,# Linux,操作系统,用户态,内核态,Linux,多线程

  • 用户态:只能操作 0-3G 范围的低位虚拟空间地址
  • 内核态:0-4G 范围的虚拟空间地址都可以操作,尤其是对 3-4G 范围的高位虚拟空间地址必须由内核态去操作
  • 补充:3G-4G 部分大家是共享的(指所有进程的内核态逻辑地址是共享同一块内存地址),是内核态的地址空间,这里存放在整个内核的代码和所有的内核模块,以及内核所维护的数据

每个进程的 4G 虚拟空间地址,高位 1G 都是一样的,即内核空间。只有剩余的 3G 才归进程自己使用,换句话说就是, 高位 1G 的内核空间是被所有进程共享的

最后做个小结,我们通过指令集权限区分用户态和内核态,还限制了内存资源的使用,操作系统为用户态与内核态划分了两块内存空间,给它们对应的指令集使用

四、CPU状态之间的转换

用户态与内核态的概念就是CPU指令集权限的区别,进程中要读写 IO,必然会用到 ring 0 级别的 C P U 指令集,而此时 CPU 的指令集操作权限只有 ring 3,为了可以操作ring 0 级别的 C P U 指令集, C P U 切换指令集操作权限级别为 ring 0,C P U再执行相应的ring 0 级别的 C P U 指令集(内核代码),执行的内核代码会使用当前进程的内核栈。

PS :每个进程都有两个栈,分别是用户栈与内核栈,对应用户态与内核态的使用

4.1 CPU状态转换的途径

用户态--->内核态:唯一途径是通过中断、异常、陷入机制(访管指令)

内核态--->用户态:设置程序状态字PSW

4.2 CPU状态转化流程

相信大家都听过这样的话「用户态和内核态切换的开销大」,但是它的开销大在那里呢?简单点来说状态转化有下面几步:

  1. 保留用户态现场(上下文、寄存器、用户栈等)
  2. 复制用户态参数,用户栈切到内核栈,进入内核态
  3. 额外的检查(因为内核代码对用户不信任)
  4. 执行内核态代码
  5. 复制内核态代码执行结果,回到用户态
  6. 恢复用户态现场(上下文、寄存器、用户栈等)

实际上操作系统会比上述的更复杂,这里只是个大概,我们可以发现一次切换经历了「用户态 -> 内核态 -> 用户态」。

用户态要主动切换到内核态,那必须要有入口才行,实际上内核态是提供了统一的入口,下面是Linux整体架构图

核心态与用户态,操作系统,# Linux,操作系统,用户态,内核态,Linux,多线程

从上图我们可以看出来通过系统调用将Linux整个体系分为用户态和内核态,为了使应用程序访问到内核的资源,如CPU、内存、I/O,内核必须提供一组通用的访问接口,这些接口就叫系统调用

库函数就是屏蔽这些复杂的底层实现细节,减轻程序员的负担,从而更加关注上层的逻辑实现,它对系统调用进行封装,提供简单的基本接口给程序员。

Shell顾名思义,就是外壳的意思,就好像把内核包裹起来的外壳,它是一种特殊的应用程序,俗称命令行。Shell也是可编程的,它有标准的Shell 语法,符合其语法的文本叫Shell脚本,很多人都会用Shell脚本实现一些常用的功能,可以提高工作效率。

4.3 什么情况会导致用户态到内核态切换

通常来说,以下三种情况会导致用户态到内核态的切换

1、系统调用

这是用户态进程主动要求切换到内核态的一种方式用户态进程通过系统调用申请使用操作系统提供的服务程序完成工作。比如fork()实际上就是执行了一个创建新进程的系统调用。

而系统调用的机制其核心还是使用了操作系统为用户特别开放的一个中断来实现,例如Linux的int 80h中断。

用户程序通常调用库函数,由库函数再调用系统调用,因此有的库函数会使用户程序进入内核态(只要库函数中某处调用了系统调用),有的则不会。

2、异常

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

3、外围设备的中断

当CPU在执行用户态的进程时,外围设备完成用户请求的操作后,会向CPU发出相应的中断信号,这时CPU会暂停执行下一条即将要执行的指令转而去执行与中断信号对应的处理程序,

如果先前执行的指令是用户态下的程序,那么这个转换的过程自然也就发生了由用户态到内核态的切换。比如硬盘读写操作完成,系统会切换到硬盘读写的中断处理程序中执行后续操作等。

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

五、为什么要有用户态和内核态

这个主要是访问能力的限制的考量,计算机中有一些比较危险的操作,比如设置时钟、内存清理,这些都需要在内核态下完成,如果随意进行危险操作,极容易导致系统崩坏。

六、内核态与用户态的区别

  • 内核态与用户态是操作系统的两种运行级别,当程序运行在3级特权级上时,就可以称之为运行在用户态。因为这是最低特权级,是普通的用户进程运行的特权级,大部分用户直接面对的程序都是运行在用户态;
  • 当程序运行在0级特权级上时,就可以称之为运行在内核态。
  • 运行在用户态下的程序不能直接访问操作系统内核数据结构和程序。当我们在系统中执行一个程序时,大部分时间是运行在用户态下的,在其需要操作系统帮助完成某些它没有权力和能力完成的工作时就会切换到内核态(比如操作硬件)。

总结:这两种状态的主要差别是

  • 处于用户态执行时,进程所能访问的内存空间和对象受到限制,其所处于占有的处理器是可被抢占的
  • 处于内核态执行时,则能访问所有的内存空间和对象,且所占有的处理器是不允许被抢占的。

参考文章:https://blog.csdn.net/m0_37199770/article/details/113482312文章来源地址https://www.toymoban.com/news/detail-751611.html

到了这里,关于【操作系统】一篇文章带你快速搞懂用户态和内核态的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Golang】一篇文章带你快速了解Go语言&为什么你要学习Go语言

    目录 1. 为什么互联网世界需要Go语言 1.1 硬件限制:摩尔定律已然失效  1.2 Go语言为并发而生 1.3 Go性能强悍 1.4 Go语言简单易学 1.4.1 语法简洁 1.4.2 代码风格统一 1.4.3开发效率高  2.Go语言的诞生与发展 2.1什么是Go语言   2.2 Go语言的诞生 2.3 Go Gopher——Go语言的吉祥物 3. 为什么

    2024年02月04日
    浏览(66)
  • MES系统是什么?一篇文章带你认识MES系统

    MES即制造执行系统(Manufacturing Execution System),它是一套面向制造企业车间执行层的生产信息化管理系统,可以为企业提供包括制造数据管理、计划排程管理、生产调度管理、库存管理、质量管理、人力资源管理、工作中心/设备管理等等多项管理模块。通过这些管理模块对整

    2024年02月09日
    浏览(44)
  • b树(一篇文章带你 理解 )

    目录 一、引言 二、B树的基本定义 三、B树的性质与操作 1 查找操作 2 插入操作 3 删除操作 四、B树的应用场景 1 数据库索引 2 文件系统 3 网络路由表 五、哪些数据库系统不使用B树进行索引 1 列式数据库 2 图形数据库 3 内存数据库 4 NoSQL数据库 5 分布式数据库 六、总结 在计算

    2024年03月17日
    浏览(56)
  • 一篇文章带你入门HBase

    本文已收录至Github,推荐阅读 👉 Java随想录 微信公众号:Java随想录 目录 HBase特性 Hadoop的限制 基本概念 NameSpace Table RowKey Column TimeStamp Cell 存储结构 HBase 数据访问形式 架构体系 HBase组件 HBase读写流程 读流程 写流程 MemStore Flush 参数说明 StoreFile Compaction 参数说明 触发过程

    2024年02月08日
    浏览(62)
  • 一篇文章,带你彻底掌握接口测试!

    一、什么是接口测试? 所谓接口,是指同一个系统中模块与模块间的数据传递接口、前后端交互、跨系统跨平台跨数据库的对接。而接口测试,则是通过接口的不同情况下的输入,去对比输出,看看是否满足接口规范所规定的功能、安全以及性能方面的要求。 二、为什么要

    2024年02月10日
    浏览(53)
  • 一篇文章带你了解什么是JDK

    JDK(Java Development Kit)是Java开发工具包,它提供了开发和运行Java应用程序所需的工具、库和资源。下面是JDK的一些重点介绍: Java编译器(javac):JDK包含了Java编译器,可以将Java源代码编译为Java字节码。通过编译器,开发人员可以将Java源代码转换为可在JVM上运行的字节码文

    2024年03月19日
    浏览(98)
  • 一篇文章带你了解什么是图灵完备

    图灵完备(Turing-complete)是一个计算机科学中的概念,它指的是一种计算模型能够模拟任何其他计算模型的能力。这意味着,只要一种计算模型是图灵完备的,那么它就能够完成任何可计算的任务。 图灵完备是指一种计算机语言或计算模型具有足够的能力来模拟图灵机的所有

    2024年02月15日
    浏览(48)
  • 一篇文章带你了解SpringBoot目录结构

    前言 SpringBoot是整合Spring技术栈的一站式框架,是简化Spring技术栈的快速开发脚手架,是一个能够快速构建生产级别的Spring应用的工具。SpringBoot是目前流行的微服务框架,倡导“约定优于配置”,简化Spring项目搭建及开发过程。springboot提供了很多核心的功能,比如自动化配置

    2024年03月25日
    浏览(71)
  • 一篇文章带你搞懂前端Cookie

    浏览器Cookie相信各位点进这篇文章的小伙伴应该不陌生了,它是前端领域中一个非常重要的内容,当然也是面试的一个考点,不知道各位小伙伴是否真正掌握了Cookie呢?当然没有掌握也是没有关系的,可以跟着小编的脚步一起来学习一下前端Cookie,没有熟练掌握的小伙伴看完这

    2024年02月04日
    浏览(46)
  • 一篇文章带你实现栈的接口

    栈(Stacks)是限定在一端插入和删除的线性表。允许插入和删除的一端称为栈顶(Top),另一端称为栈底(Bottom)。栈中的数据元素遵守后进先出(Last In First Out)的原则。因此,栈又称为后进先出(先进后出)线性表。 压栈:栈的插入操作叫做进栈、压栈、入栈,入数据在

    2024年02月13日
    浏览(51)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包