用户态与内核态

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用户态与内核态相关的知识,希望对你有一定的参考价值。

参考技术A 内核态相当于一个介于硬件与应用之间的层,内核有ring 0的权限,可以执行任何cpu指令,也可以引用任何内存地址,包括外围设备, 例如硬盘, 网卡,权限等级最高。

用户态则权利有限,例如在内存分配中,有一部分内存是仅为内核态使用的,用户态code则不允许访问那些内存地址,每个进程只允许访问自己申请到的内存。而且不允许访问外围设备。另外在执行cpu指令的时候也可以被高优先级抢占。
大多数时间各类程序都是执行在用户态下,毕竟内核就是基础而已。

很多博客都提到了一个状态转换的例子:c语言在malloc的时候需要涉及到从用户态到内核态的转换,malloc是个函数,所以算作系统调用,是用户态的主动申请转换。但是在实际实现中,未必一定需要进入内核态拿到新的内存,详细看这个博客: https://blog.csdn.net/zdy0_2004/article/details/47787631

3.为什么两者切换耗时
linux下每个进程的栈有两个,一个是用户态栈,一个是内核态栈。在需要从用户态栈切换到内核的时候,需要进行执行栈的转换,保存用户态的状态,包括寄存器状态,然后执行内核态操作,操作完成后要恢复现场,切换到用户态,这个过程是耗时的。当然这里有很多细节,但是我不懂,只了解宏观上的原因。

很多人都说mutex加锁解锁很慢,为什么呢,因为他也是需要从用户态到内核态的切换,因此有一些无锁技巧例如CAS(Compare and swap),还有spin lock这种停等不作context切换的锁。
这个博客说的挺好,介绍了mutex咋切换的细节,反正我是写不出来: https://www.jianshu.com/p/5725db8f07dc

3.一些讨论
https://blog.codinghorror.com/understanding-user-and-kernel-mode/
这个博客在介绍user mode和kernel mode,但是评论里都在争论各类语言在处理exception的时候是否切换到了内核态,跑偏了🤣。这个exception不知那种缺页的系统异常,那个异常无疑是内核态来解决。这里讨论的是语言里定义的哪些异常,其中我觉得这个参考了文档的说的可能好一些(第二个评论): https://stackoverflow.com/questions/28384931/do-exceptions-explicitly-caught-and-handled-cause-switch-to-kernel-mode
我也觉得是depends on implement,异常处理要查看栈信息,可能是直接拽出来系统的栈,这种方法铁铁的需要进入内核态。如果是JVM这种自己维护了这样的栈呢?那其实就不需要去内核态拿栈。但是不管怎么说,异常处理是极其耗时的这点不会错。

另外参考的其他博客:
http://wely.iteye.com/blog/2332327
https://blog.csdn.net/xiaoaid01/article/details/51659037

Linux:用户态与内核态

文章目录

用户态与内核态

用户态与内核态的概念

用户态

用户态:也叫用户空间,是用户进程/线程所在的区域。主要用于执行用户程序。

用户态就是提供应用程序运行的空间,为了使应用程序访问到内核管理的资源例如CPU,内存,I/O。内核必须提供一组通用的访问接口,这些接口就叫系统调用。

系统调用是操作系统的最小功能单位。根据不同的应用场景,不同的Linux发行版本提供的系统调用数量也不尽相同,大致在240-350之间。这些系统调用组成了用户态跟内核态交互的基本接口

内核态

内核态:也叫内核空间,是内核进程/线程所在的区域。主要负责运行系统、硬件交互。

内核态其实从本质上说就是内核,它是一种特殊的软件程序,控制计算机的硬件资源,例如协调,CPU资源,分配内存资源,并且提供稳定的环境供应用程序运行

为什么要区分内核态和用户态

实现保护机制。防止用户进程误操作或者是恶意破坏系统。

内核态类似于C++的私有成员,只能在类内访问,用户态类似于公有成员,可以随意访问

所以说操作系统在执行用户程序时,主要工作在用户态,只有在其执行没有权限完成的任务时才会切换到内核态。

用户态与内核态的区别

内核态:运行的代码不受任何限制,CPU可以执行任何指令。

用户态:运行的代码需要受到CPU的很多检查,不能直接访问内核数据和程序,也就是说不可以像内核态线程一样访问任何有效地址。

用户态切换到内核态的方式

1、系统调用(主动)

由于用户态无法完成某些任务,用户态会请求切换到内核态,内核态通过为用户专门开放的中断完成切换。

系统调用本身就是中断,但是是软件中断,跟硬中断不同

2、异常(被动)

在执行用户程序时出现某些不可知的异常,会从用户程序切换到内核中处理该异常的程序,也就是切换到了内核态。例如:缺页异常。

3、外围设备中断(被动)

外围设备发出中断信号,当中断发生后,当前运行的进程暂停运行,并由操作系统内核对中断进程处理,如果中断之前CPU执行的是用户态程序,就相当于从用户态向内核态的切换。

用户态与内核态空间分配

对 32 位操作系统而言,它的寻址空间(虚拟地址空间,或叫线性地址空间)为 4G(2的32次方)。也就是说一个进程的最大地址空间为 4G。操作系统的核心是内核(kernel),它独立于普通的应用程序,可以访问受保护的内存空间,也有访问底层硬件设备的所有权限。为了保证内核的安全,现在的操作系统一般都强制用户进程不能直接操作内核。具体的实现方式基本都是由操作系统将虚拟地址空间划分为两部分,一部分为内核空间,另一部分为用户空间。针对 Linux 操作系统而言,最高的 1G 字节点(从虚拟地址 0xC0000000 到 0xFFFFFFFF)由内核使用,称为内核空间。而较低的 3G 字节点(从虚拟地址 0x00000000 到 0xBFFFFFFF)由各个进程使用,称为用户空间。

对上面这段内容我们可以这样理解:

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

现代的操作系统大都通过内核空间和用户空间的设计来保护操作系统自身的安全性和稳定性

所以说啊,这篇里的概念原理其实都是一种思想,每个操作系统都不一样,一般就是拿Linux说。

以上是关于用户态与内核态的主要内容,如果未能解决你的问题,请参考以下文章

用户态与内核态

用户态与内核态的理解

用户态与内核态

小知识点记录:内核态与用户态

小知识点记录:内核态与用户态

linux用户态与内核态