CPU的用户态和内核态

内核从本质上看是一种软件——控制计算机的硬件资源
用户态和内核态也可以说是对应系统执行权限的一个分级
个人理解慎浅,多是参考别人的文章,日后工作之于在研究


指令集

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

我理解的就是:对于我们的编程而言,我们做的就是去合理高效的去利用CPU提供的这些指令集中的命令,去操作真实的硬件,来完成真正的系统操作。
在这里插入图片描述

在这里插入图片描述

一、用户态

运行用户程序的

用户态的使用命令是非特权指令,例如控制转移 算数运算 取数指令 访管指令(使用户程序从用户态陷入内核态)

特权级别: R3相当于用户态;

执行状态 : 进程能够访问的内存空间和对象被限制,而且占有的处理器可以被抢占的

二、内核态

运行操作系统程序,操作硬件

**能操作内核的就是特权指令:**用户程序不能操作特权指令 。举例:启动I/O 内存清零 修改程序状态字 设置时钟 允许/禁止终端 停机

特权级别: R0相当于内核态

执行状况: 执行时可以访问所有的内存空间和对象,而且占用的处理器是不能被抢占的。

三、用户态和内核态切换状态

用户程序跑在用户态下,但是如果需要执行一些操作例如申请内存,网络读写时(外部资源的调用时),自己的权限不够,就需要转换到内核态去让内核的code帮忙干一些事情。
外部资源:声卡 内存 硬盘等设备都可以称为外部资源

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

发生异常:
当CPU在执行运行在用户态下的程序时,发生了某些事先不可知的异常,这时会触发由当前运行进程切换到处理此异常的内核相关程序中,也就转到了内核态,比如缺页异常。
((英语:Page fault,又名硬错误、硬中断、分页错误、寻页缺失、缺页中断、页故障等),指的是当软件试图访问已映射在虚拟地址空间中,但是并未被加载在物理内存中的一个分页时,由中央处理器的内存管理单元所发出的中断。 缺页中断就是要访问的页不在主存,需要操作系统将其调入主存后再进行访问。在这个时候,被内存映射的文件实际上成了一个分页交换文件。 简单讲,就是:内核接住了这个异常,并处理了这个异常(Page Fault Handler)。)

外围设备的中断

当外围设备完成用户请求的操作后,会向CPU发出相应的中断信号,这时CPU会暂停执行下一条即将要执行的指令转而去执行与中断信号对应的处理程序,
如果先前执行的指令是用户态下的程序,那么这个转换的过程自然也就发生了由用户态到内核态的切换。比如硬盘读写操作完成,系统会切换到硬盘读写的中断处理程序中执行后续操作等。
这3种方式是系统在运行时由用户态转到内核态的最主要方式,其中系统调用可以认为是用户进程主动发起的,异常和外围设备中断则是被动的。

四、态切换的消耗

在这里插入图片描述
用户态要主动切换到内核态,那必须要有入口才行,实际上内核态是提供了统一的入口,从上图我们可以看出来通过系统调用将Linux整个体系分为用户态和内核态,为了使应用程序访问到内核的资源,如CPU、内存、I/O,内核必须提供一组通用的访问接口,这些接口就叫系统调用。

开销问题
上下文切换 :几十纳秒到数微妙的CPU时间

1.线程切换-同一进程中的两个线程之间的切换
2.进程切换-两个进程之间的切换
3.模式切换-在给定线程中,用户模式和内核模式的切换

  • 上下文的切换时,CPU会停止处理当前运行的程序,并保存当前程序运行的具体位置以便之后继续运行,这个信息是保存在进程控制块( PCB ,process control block )
  • PCB 通常是系统内存区中的一个连续的存区,它存放着操作系统用于描述进程情况及控制进程运行所需的全部信息

4.1、上下文切换执行的步骤

  1. 保存进程A的状态(寄存器和操作系统数据);
  2. 更新PCB中的信息,对进程A的“运行态”做出相应更改;
  3. 将进程A的PCB放入相关状态的队列;
  4. 将进程B的PCB信息改为“运行态”,并执行进程B;
  5. B执行完后,从队列中取出进程A的PCB,恢复进程A被切换时的上下文,继续执行A;

4.2、CPU的上下文切换

  • 把前一个任务的CPU上下文(CPU寄存器和程序计数器-内核栈)保存,然后加载新任务的上下文到寄存器和程序计数器中,跳转到程序计数器所指向的位置,开始执行任务。

客户端的多个请求在多线程时使用会涉及到cpu的上下文切换 ,操作句柄

进程切换

进程资源(用户态的虚拟内存、栈,内核态的栈和硬件上下文-CPU寄存器)

  1. 切换页目录以使用新的地址空间(刷新新进程的虚拟内存和用户栈,当虚拟内存更新后,TLB也需要更新)
  2. 切换内核栈和硬件上下文

线程切换

1.切换内核栈和硬件上下文线程的切换虚拟内存空间依然是相同的(TLB),但是进程切换是不同的

多线程下的上下文切换的主要损耗

linux2.6 jvm1.8采用的是1对1线程模型,线程调度是由os内核完成(内核态),同一个进程种多线程的上下文切换不需要更新虚拟内存,而且只有一次cpu上下文切换
注意
cpu时间片,不同进程想要执行必须获得cpu时间片,这个是由内核决定,完全公平调度
线程调度就是由内核来完成的,这个过程中,应该涉及到的是内核程序获取cpu时间片,执行内核态操作,主要损耗是在cpu内核和用户进程切换导致的损耗,这个是无法避免的

正常系统调用的损耗

从用户态切换到内核态,通过系统调用的方式,CPU上下文切换的:切换时,先保存CPU寄存器中用户态的指令位置,再重新更新为内核指令的位置。当系统调用结束时,CPU寄存器恢复到原来保存的用户态。一次系统调用,发生了两次CPU上下文切换。

  • 几乎所有的系统调用都需要内核态的权限去配合执行 ,

五、切换的过程 和原理

CS寄存器的低两位,叫做CPL(当前特权级),在linux中,有两种状态,就是0和3,0表示内核态,3表示用户态,GDT表和IDT表(中断向量表)中的13位和14位,叫做DPL(目标特权级)。只有当DPL>= CPL时,CPU才允许应用程序进入到内核中,也就是此时为内核态。以系统调用为例子,当发生系统调用时,会产生一个 INT 0x80 中断,接下来CPU自动查中断向量表(CPU的功能),此时CPL = 3(用户态),在表中查 0x80
对应的程序执行,0x80对应的程序是将CPL改为 0,也就是内核态,到这里就已经发生了用户态到内核态的切换了,然后接下来就是一系列的指令执行…

特权级别是用来管理和控制程序执行的手段
Intel x86架构的CPU来说一共有0~3四个特权级,0级最高,3级最低
,硬件上在执行每条指令时都会对指令所具有的特权级做相应的检查,相关的概念有CPL、DPL和RPL,这里不再过多阐述。

参考文章

作者 : Gizing 用户态和内核态的区别

作者:程序猿阿星 :从根上理解用户态与内核态

作者:听海吹牛逼的声音
链接:https://www.jianshu.com/p/38ea929e1668
来源:简书

作者:邵红晓
链接:https://www.jianshu.com/p/5028573f1ab5
来源:简书

作者 :农民伯伯-Coding

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Network porter

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值