用户态和内核态切换开销_进程切换在用户态还是内核态

用户态和内核态切换开销_进程切换在用户态还是内核态1.切换方式从用户态到内核态切换可以通过三种方式,或者说会导致从用户态切换到内核态的操作:系统调用,这个上面已经讲解过了,在我公众号之前的文章也有讲解过。其实系统调用本身就是中断,但是软件中断,跟硬中断不同。系统调用机制是使用了操作系统为用户特别开放的一个中断来实现,如Linux的int80h中断。 异常:如果当前进程运行在用户态,如果这个时候发生了异常事件,会触发由当前运行进程切换到处理此异常的内核相关进程中 外围设备中断:外围设备完成用户请求的操作之后,会向CPU发出中断信号,这

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

1. 切换方式

从用户态到内核态切换可以通过三种方式,或者说会导致从用户态切换到内核态的操作:

  • 系统调用,这个上面已经讲解过了,在我公众号之前的文章也有讲解过。其实系统调用本身就是中断,但是软件中断,跟硬中断不同。系统调用机制是使用了操作系统为用户特别开放的一个中断来实现,如 Linux 的 int 80h 中断。
  • 异常:如果当前进程运行在用户态,如果这个时候发生了异常事件,会触发由当前运行进程切换到处理此异常的内核相关进程中
  • 外围设备中断:外围设备完成用户请求的操作之后,会向CPU发出中断信号,这时CPU会转去处理对应的中断处理程序。

2. 代价何在

当发生用户态到内核态的切换时,会发生如下过程(本质上是从“用户程序”切换到“内核程序”)

  • 设置处理器至内核态。
  • 保存当前寄存器(栈指针、程序计数器、通用寄存器)。
  • 将栈指针设置指向内核栈地址。
  • 将程序计数器设置为一个事先约定的地址上,该地址上存放的是系统调用处理程序的起始地址。

而之后从内核态返回用户态时,又会进行类似的工作。

3. 如何避免频繁切换

用户态和内核态之间的切换有一定的开销,如果频繁发生切换势必会带来很大的开销,所以要想尽一切办法来减少切换。这也是面试常考的问题。

3.1 减少线程切换

因为线程的切换会导致用户态和内核态之间的切换,所以减少线程切换也会减少用户态和内核态之间的切换。那么如何减少线程切换呢?

  • 无锁并发编程。多线程竞争锁时,加锁、释放锁会导致比较多的上下文切换。(为什么加锁和释放锁会导致上下文切换,看文末的补充解释)
  • CAS算法。使用CAS避免加锁,避免阻塞线程
  • 使用最少的线程。避免创建不需要的线程
  • 协程。在单线程里实现多任务的调度,并在单线程里维持多个任务间的切换

3.2 一个面试问题

I/O 频繁发生内核态和用户态切换,怎么解决。

首先要同意这个说法,即I/O会导致系统调用,从而导致内核态和用户态之间的切换。因为对I/O设备的操作是发生在内核态。那如何减少因为I/O导致的系统调用呢?答案是:使用户进程缓冲区。下面解释一下原因

用户态和内核态切换开销_进程切换在用户态还是内核态

用户进程缓冲区

你看一些程序在读取文件时,会先申请一块内存数组,称为buffer,然后每次调用read,读取设定字节长度的数据,写入buffer。之后的程序都是从buffer中获取数据,当buffer使用完后,在进行下一次调用,填充buffer。所以说:用户缓冲区的目的就是是为了减少系统调用次数,从而降低操作系统在用户态与核心态切换所耗费的时间。除了在进程中设计缓冲区,内核也有自己的缓冲区。

内核缓存区

当一个用户进程要从磁盘读取数据时,内核一般不直接读磁盘,而是将内核缓冲区中的数据复制到进程缓冲区中。但若是内核缓冲区中没有数据,内核会把对数据块的请求,加入到请求队列,然后把进程挂起,为其它进程提供服务。等到数据已经读取到内核缓冲区时,把内核缓冲区中的数据读取到用户进程中,才会通知进程,当然不同的IO模型,在调度和使用内核缓冲区的方式上有所不同。

小结

图中的read,write和sync都是系统调用。read是把数据从内核缓冲区复制到进程缓冲区。write是把进程缓冲区复制到内核缓冲区。当然,write并不一定导致内核的缓存同步动作sync,比如OS可能会把内核缓冲区的数据积累到一定量后,再一次性同步到磁盘中。这也就是为什么断电有时会导致数据丢失。所以说内核缓冲区,可以在OS级别,提高磁盘IO效率,优化磁盘写操作。

4. 补充解释

为什么加锁和释放锁会导致上下文切换

Synchronized是通过对象内部的一个叫做监视器锁(monitor)来实现的。但是监视器锁本质又是依赖于底层的操作系统的Mutex Lock来实现的。但是由于使用Mutex Lock需要将当前线程挂起并从用户态切换到内核态来执行,这种切换的代价是非常昂贵的因此,这种依赖于操作系统Mutex Lock所实现的锁我们称之为“重量级锁”。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/192121.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • ubuntu中文社区_linux中文系统

    ubuntu中文社区_linux中文系统“新氧ubuntu中文定制版”是由新氧ubuntu中文定制版项目组在近期推出的一个基于Ubuntu的中文Linux发行版。根据其描述:新氧ubuntu中文定制版,是基于ubuntu官方发布版制作的中文优化应用版本。它不是一个新的发布版。新氧ubuntu中文定制版是一个非盈利项目,因为其包含了一些独特的适用于中文用户的组件,一经推出就受到了广泛的关注。新氧ubuntu…

    2022年10月21日
    0
  • Java面试题大全带答案「建议收藏」

    Java面试题大全带答案「建议收藏」本人发现网上虽然有不少Java相关的面试题,但第一未必全,第二未必有答案,第三虽然有答案,但未必能在面试中说,所以在本文里,会不断收集各种面试题,并站在面试官的立场上,给出我自己的答案。第一部分、Java基础1.JDK和JRE有什么区别?JDK是java的开发工具包,有JDK8,9甚至到14的差别,安装以后,不仅包含了java的开发环境,比如java.exe,还包含了运行环境(jre)相关包。 JRE是java运行环境,一般装好JDK后,系统里会有对应的JRE环境。2..

    2022年6月21日
    31
  • 亚马逊AWS服务器CentOS/Linux系统Shell安装Nginx及配置自启动

    亚马逊AWS服务器CentOS/Linux系统Shell安装Nginx及配置自启动

    2022年2月9日
    58
  • 【Unity技能】做一个简单的NPC

    【Unity技能】做一个简单的NPC

    2022年1月2日
    50
  • QT多线程实战_Qt多线程开发项目

    QT多线程实战_Qt多线程开发项目文章目录需求的提出多线程线程间通信需求的提出窗口本身就是一个死循环,在这样一个死循环中执行任何耗时的操作,都会导致程序崩溃。所以多线程对于窗口编程而言是必要的。例如,在窗口中拖入一个pushButton和lineEdit,将pushButton的名字改为pbStart,然后为其绑定一个函数,函数中创建一个死循环,并让死循环中的内容实时输出到lineEdit。接下来设计一个逻辑,当点击pbStart之后,开始执行死循环,同时按钮内容变为Stop;当按钮内容为Stop时,点击按钮,停止执行死循环。所以

    2025年6月1日
    0
  • python 字符转义(url中文转义)

    URL特殊字符需转义1、空格换成加号(+)2、正斜杠(/)分隔目录和子目录3、问号(?)分隔URL和查询4、百分号(%)制定特殊字符5、#号指定书签6、&号分隔参数转义字符的原因:如果你的表单使用get方法提交,并且提交的参数中有“&”等特殊符的话,如果不做处理,在service端就会将&后面的作为另外一个参数…

    2022年4月14日
    76

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号