用户态和内核态的区别是啥
这篇文章的深度不会太深,重点就是了解一下用户态和内核态的区别就 OK 了。
先给不了解内核态、用户态的简单介绍一下,我们在什么时候会提到这两个概念。
例如我们的应用程序需要从磁盘读取某个文件的数据,此时并不是直接从磁盘加载到应用内存中,而是:
- 先将数据从「磁盘」复制到「内核 Buffer」
- 再将数据从「内核 Buffer」复制到「用户 Buffer」
以上就是用户态和内核态的概念。首先我们给他下个定义,这两个态是操作系统的运行级别。
然后我们知道,我们写的程序,最终运行的时候实际都会被编译、解释成一条一条的 CPU 指令被 CPU 执行。
用户态、内核态的指令都是 CPU 都在执行,所以我们可以换个说法,实际上这个态代表的是当前 CPU 的状态。那既然这些指令最终都由 CPU 执行,那对其区分的理由是什么呢?
那是因为,CPU 指令根据其重要的程度,也分为不同的权限。有一些指令执行失败了无关痛痒,而有一些指令失败了会导致整个操作系统崩溃,甚至需要重启系统。如果将这些指令随意开放给应用程序的话,整个系统崩溃的概率将会大大的增加。
再举个类似的例子。我们设计一个类,里面有几个很重要的变量,你大概率是不会把它们声明成 public
的吧?应该声明成 private
,并开发几个专门修改他们的方法,对传入的值进行一系列的校验之后再去设置。
上面说到,CPU 指令是做了权限划分的, 例如 Intel X86 中将 CPU 指令权限划分为了 4 个等级:
它们之间的权限的高低程度可以通过这张图来识别:
上图中的 IA 指的是 Intel Architecture
所以可以看到,越靠近的核心的权限越高。换句话说,权限由高到低为:Ring0 > Ring1 > Ring2 > Ring3
在 Linux 系统中,由于只有 Ring0 和 Ring3 级别的指令,所以我们可以对用户态、内核态给一个更细节的区别描述:运行 Ring0 级别指令的叫内核态,运行 Ring3 级别指令的叫用户态。
了解了指令集权限的概念,我们就可以再更正一下上面的描述:什么态实际上代表的是当前 CPU 正在执行什么级别的指令
知道了用户态和内核态的区别、以及为什么要对其进行区别之后,我们就可以来看什么时候会从用户态切换到内核态了。
答案是发生系统调用的时候
那什么又是系统调用呢?看这张图
当用户态的程序需要向操作系统申请更高权限的服务时,就通过系统调用向内核发起请求。
内核自然也会提供很多的接口来供调用,例如申请动态内存空间。但是申请了内存是不是还得考虑释放内存?如果把这块内存管理交给应用程序的话,复杂的管理工作会给开发带来很多负担。
所以库函数就是用于屏蔽掉内部复杂的细节的,我们的应用程序可以通过库函数来调用内核的提供的接口,而库函数就会发起系统调用,发起了系统调用之后,用户态就会切换成内核态去执行对应的内核方法。
除了系统调用之外,还有另外两种会导致态的切换:发生异常、中断。
本篇文章已放到我的 Github github.com/sh-blog 中,欢迎 Star。微信搜索关注【SH的全栈笔记】,回复【队列】获取MQ学习资料,包含基础概念解析和RocketMQ详细的源码解析,持续更新中。
如果你觉得这篇文章对你有帮助,还麻烦点个赞,关个注,分个享,留个言。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
解放生产力「GitHub 热点速览 v.21.51」
作者:HelloGitHub-小鱼干 解放生产力一直都是我们共同追求的目标,能在摸鱼的空闲把💰赚了。而大部分好用的工具便能很好地解放我们的生产力,比如本周特推 RedisJSON 不用对 JSON 做哈希也能直接用 Redis 存储、读取 JSON 数据,省时省力。同样的,能节省生产力的 Turborepo 能免去多框架构建的繁琐,节省你的构建时间,还有 mold 链接器,性能蹭蹭地节省的都是你的时间。 以下内容摘录自微博@HelloGitHub 的 GitHub Trending 及 Hacker News 热帖(简称 HN 热帖),选项标准:新发布 | 实用 | 有趣,根据项目 release 时间分类,发布时间不超过 14 day 的项目会标注 New,无该标志则说明项目 release 超过半月。由于本文篇幅有限,还有部分项目未能在本文展示,望周知 🌝 本文目录 本周特推 1.1 Redis 原生 JSON:RedisJSON 1.2 高性能构建系统:turborepo GitHub Trending 周榜 2.1 射击游戏:space-shooter.c 2.2 任务管理...
- 下一篇
Kubernetes 集群无损升级实践
一、背景 活跃的社区和广大的用户群,使 Kubernetes 仍然保持3个月一个版本的高频发布节奏。高频的版本发布带来了更多的新功能落地和 bug 及时修复,但是线上环境业务长期运行,任何变更出错都可能带来巨大的经济损失,升级对企业来说相对吃力,紧跟社区更是几乎不可能,因此高频发布和稳定生产之间的矛盾需要容器团队去衡量和取舍。 vivo 互联网团队建设大规模 Kubernetes 集群以来,部分集群较长时间一直使用 v1.10 版本,但是由于业务容器化比例越来越高,对大规模集群稳定性、应用发布的多样性等诉求日益攀升,集群升级迫在眉睫。集群升级后将解决如下问题: 高版本集群在大规模场景做了优化,升级可以解决一系列性能瓶颈问题。 高版本集群才能支持 OpenKruise 等 CNCF 项目,升级可以解决版本依赖问题。 高版本集群增加的新特性能够提高集群资源利用率,降低服务器成本同时提高集群效率。 公司内部维护多个不同版本集群,升级后减少集群版本碎片化,进一步降低运维成本。 这篇文章将会从0到1的介绍 vivo 互联网团队支撑在线业务的集群如何在不影响原有业务正常运行的情况下从 v1.10 ...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- MySQL8.0.19开启GTID主从同步CentOS8
- CentOS8安装Docker,最新的服务器搭配容器使用
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- Hadoop3单机部署,实现最简伪集群
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- CentOS关闭SELinux安全模块
- Linux系统CentOS6、CentOS7手动修改IP地址
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作