用户态内核态浅析

用户态与内核态定义

用户态与内核态实际上是cpu运行在两种不同的权限级别上,inter架构将cpu指令按照权限级别由高到低分为4个等级,分别是ring0、ring1、ring2、ring3。而windows实现将所有指令划分为2个级别,即ring0和ring3。ring0级别的cpu指令仅由内核程序使用,ring3则是所有程序(包含用户程序)均可使用,当用户程序尝试执行ring0级别的cpu指令时将出现非法指令错误。因此从执行指令集来看,当cpu运行全是ring3级别指令集的程序时则是处于用户态上,反之当cpu运行包含ring0级别的指令集的程序时则处于内核态上。

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

这个问题实际上可以转换为为很么要对cpu的指令划分级别,在早期还不存在操作系统的计算机中,一台计算机只运行一个程序,想要运行另一个程序必须等待当前程序运行完成。随着硬件技术的不断发展,cpu的运行速度不断提升,一台计算机只运行一个程序会造成cpu性能的浪费;其次从人们使用计算的角度来看也更希望一台计算机能通知运行多个程序,因此操作系统应运而生。

那为什么运行多个程序就需要操作系统?当一台计算机运行一个程序时,该程序具备全局硬件权限,所有的硬件均为该程序服务,因此程序可以随时支配所有硬件。但当运行多个程序时,必然会带来以下问题

  • 关于cpu:必须要通过一定的控制手段让cpu轮流去执行多个任务,
  • 关于内存:各程序间的内存不能相互影响,需要相互独立,当一个程序需要更多的内存时不能随机使用其它内存,因为其它内存可能被其它程序所占用,需要要给全局内存管理程序来分配空闲内存给该程序。
  • 关于io:就像cpu一样,io设备在确定的时刻也只能执行一项任务,因此当一个程序还在使用io时,虽然此时切换到另一个程序运行,但当该程序要使用io时,必须等待io任务完成。
    为了有效的协调多程序对硬件的有序访问,一个控制程序有序访问硬件的程序诞生了,实际上操作系统的发展经历了多个时代,从早期的多道程序系统、分时系统、实时系统到如今的通用操作系统,操作系统的发展伴随着硬件技术的发展和人们需求不断的变更。到了这里再来回复开头的问题,为什么要区分用户态和内核态?:这是为了保证多程序能够基于一种可管理、可分配、有序的方式访问硬件资源。对于内存而言,当一个程序需要更多内存时,应该向操作系统请求分配内存,操作系统根据内存空闲情况分配未使用的内存交由程序使用;对于需要更多执行时间的程序而言,需要操作系统基于特定的算法为程序分配更多的cpu时间片;对于io来说,操作系统基于一定的顺序算法依次执行IO任务。

如何实现用户态和内核态的切换

现代计算机通过系统调用来实现cpu用户态和内核态的切换,而系统调用的本质是中断处理。什么是中断处理?cpu总是有条不紊的执行程序指令,但在很多情况下人们希望cpu能够实时处理外部请求,比如当敲击键盘或者点击鼠标时,需要cpu能立即暂停当前正在执行的任务转而去响应键盘或鼠标请求;现代cpu有一个特定的引脚来接受中断请求,cpu在执行完成每一条指令后会去检测该引脚是否收到中断请求,如果存在中断则响应中断。实际上硬件并不直接向cpu引脚发送中断信号,而是将中断信号发送到中断控制器,由中断控制器统一管理并根据相应的规则向cpu发送中断请求,这类由硬件产生的中断称之为硬中断。cpu在响应中断时需要完成以下工作:暂停当前正在执行的任务,这需要保存cpu运行上下文,上下文包含PSW(Program Status Word:程序状态字)、程序计数器(即当前任务的下一条执行地址)以及其它寄存器信息。这一系列操作被称之为保护现场;之后才能去执行中断任务,当中断任务执行完成后需要重新恢复之前的上下文继续执行任务后继逻辑。

相对于硬中断,cpu提供了特定指令(INT n)可以实现暂停当前正在执行的任务,然后根据n的值去执行特定的中断程序,这个动作和硬中断非常相似,区别只在于硬中断通过检测中断信号发起的中断响应,而软中断则是通过执行特定指令发起的中断响应,因此也称软中断为陷入内核。

用户级程序并不存在ring0级别的cpu指令,而是相应的软中断指令(INT n)进行替代,而软中断指令n通常对应的时一个完整的中断程序(由若干ring0指令以及ring3指令构成),这些程序被称为内核程序,通过中断方式执行这些内核程序的过程被称为系统调用。

分析Java synchronized中用出现的用户态内核态切换问题

这里不在详述synchronized的原理和逻辑,在jdk1.5以及之前、synchronized被称之为重量级锁,相比于ReentrantLock,在锁竞争激烈的时候synchronized效率比ReentrantLock差很多,其本质原因在于synchronized在出现锁竞争且竞争失败时将无条件进入阻塞状态,而线程的阻塞和唤醒操作需要通过系统调用实现,而系统调用意味着用户态和内核态的切换,因此会降低效率,尤其在频繁的阻塞、唤醒竞争锁的情况下更是严重影响性能,jdk1.6之后synchronized引入了锁升级的优化,其次在出现锁竞争失败的情况下不会直接进入阻塞,而是通过一定的自旋时间重复尝试是否可获取到锁(通常线程占用的锁的时间非常短,因此空转cpu一段时间后有机会获取到锁,这里的空转时间相比阻塞唤醒获取到锁要高效得多),自旋时间与最近一次线程获取锁的自旋时间和结果有关,。因此从重量级锁来说其优化的关键点在于增加cpu自旋操作来尝试获取锁,降低锁竞争时阻塞和唤醒线程引起的性能消耗。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值