精华内容
下载资源
问答
  • 最近开发用到fuse文件系统,这个文件系统的功能实现是在用户态下进行的,然而它的文件系统操作接口必须在内核态注册,所以需要研究一下内核态用户态开销到底如何。 下面这个例子是在stackoverflow上看到的,基本...

    最近开发用到fuse文件系统,这个文件系统的功能实现是在用户态下进行的,然而它的文件系统操作接口必须在内核态注册,所以需要研究一下内核态到用户态的开销到底如何。
    下面这个例子是在stackoverflow上看到的,基本能反映开销的差异了:
    在linux测试这个测试程序,getuid是一个系统调用,返回当前用户的id

    复制代码

    1 #include <unistd.h>
    2 
    3 #define MAX 100000000
    4 int main() {
    5   int ii;
    6   for (ii=0; ii<MAX; ii++) getuid();
    7   return 0;
    8 }

    复制代码

    结果显示循环1亿次用时8秒多
    real 0m8.438s
    user 0m3.952s
    sys 0m4.485s

    当使用如下程序测试时,

    复制代码

     1 #include <unistd.h>
     2 #define MAX 100000000
     3 
     4 int _getid()
     5 {
     6         return 1;
     7 }
     8 
     9 int main() {
    10   int ii;
    11   for (ii=0; ii<MAX; ii++) _getid();
    12   return 0;
    13 }

    复制代码

    运行结果如下:

    real 0m0.305s
    user 0m0.304s
    sys 0m0.000s

    这时时间消耗明显减少了很多。

    两个程序时间的消耗的差异主要在于内核态和用户态的切换,每一次循环都涉及一次用户态->内核态->用户态的切换,所以消耗的时间就多了很多。

    同时也说明我必须要修改fuse的各个文件接口的功能实现来让它不再反复切换用户内核态了。

    展开全文
  • 总的来说,就是线程切换或者加锁解锁都是因为需要用户态和内核态切换,从而导致的开销大。 应用程序的执行需要依托内核提供的资源,包括CPU、存储、IO等,因此内核提供了一个统一的接口, 也就是系统调用,一个...

    用户态和内核态的切换耗费时间的原因

    总的来说,就是线程切换或者加锁解锁都是因为需要用户态和内核态的切换,从而导致的开销大。
    应用程序的执行需要依托内核提供的资源,包括CPU、存储、IO等,因此内核提供了一个统一的接口,
    也就是系统调用,一个应用程序从用户态进入到内核态,就需要执行系统调用。
    用户态转化为内核态时,需要执行系统调用,保存现场,也就是保存用户态的寄存器等,
    然后去系统调用,并在内核态执行,最后恢复现场。并且由于内核对于用户的不信任,
    因此内核需要对用户进行一些额外的检查,这就需要耗费更多的工作了。
    

    用户态和内核态

    用户态和内核态:
    1、划分的原因:为了防止用户进程破坏操作系统的稳定,对一些资源的访问进行了等级划分,与系统相关的一些关键性操作必须由高级别的程序来完成,这样可以做到集中管理,减少冲突。
    2、两者的区别:内核态和用户态是操作系统的两种运行级别,总共有四种运行级别,分别为 R0、R1、R2和 R3。
    内核态权限最高,为 R0 级,用户态权限最低,为 R3 级。
    用户态运行用户程序,进程所能访问的内存空间和对象受到很大的限制,所占有的处理机可被抢占;
    内核态运行操作系统程序,能访问所有的内存空间和对象,所占有的处理机不可被抢占。
    
    用户态和内核态的切换:
    进程大部分时间运行在用户态下 ,在其需要操作系统帮助完成一些用户态特权以外的操作时就会切换到内核态 。 
    切换到内核态的方式有 : 系统调用(父进程fork一个子进程)、发生异常、外围设备中断。
    
    展开全文
  • 用户态切换内核态的过程如下 开销的地方 1、切换线程上下文,需要保护恢复寄存器数据 2、切换到执行内核线程的时候,内核代码对用户不信任,需要进行额外的检查。 3、内核线程执行完返回过程有很多额外工作...

     Synchronized 是基于底层操作系统的 Mutex Lock 实现的,每次获取和释放锁操作都会带来用户态和内核态的切换,从而增加系统性能开销。

    用户态切换内核态的过程如下

    开销的地方

    1、切换线程上下文,需要保护和恢复寄存器数据

    2、切换到执行内核线程的时候,内核代码对用户不信任,需要进行额外的检查。

    3、内核线程执行完返回过程有很多额外工作,比如检查是否需要调度等

    4、如果被切换的线程属于不同用户程序间切换的话,那么还要更新cr3寄存器,这样会更换每个程序的虚拟内存到物理内存映射表的地址

    展开全文
  • 锁开销上下文切换开销

    千次阅读 2017-07-07 10:21:47
    一、互斥锁的开销主要在内核态用户态切换:  申请锁时,从用户态进入内核态,申请到后从内核态返回用户态(两次切换);没有申请到时阻塞睡眠在内核态。使用完资源后释放锁,从用户态进入内核态,唤醒阻塞等待...

    一、互斥锁的开销主要在内核态与用户态的切换:

      申请锁时,从用户态进入内核态,申请到后从内核态返回用户态(两次切换);没有申请到时阻塞睡眠在内核态。使用完资源后释放锁,从用户态进入内核态,唤醒阻塞等待锁的进程,返回用户态(又两次切换);被唤醒进程在内核态申请到锁,返回用户态(可能其他申请锁的进程又要阻塞)。所以,使用一次锁,包括申请,持有到释放,当前进程要进行四次用户态与内核态的切换。同时,其他竞争锁的进程在这个过程中也要进行一次切换。

      进程上下文切换的直接消耗包括CPU寄存器保存和加载,需要调度时有内核调度代码的执行。

     

    二、自旋锁:

      与互斥锁不同的是自旋锁不会引起调用者睡眠。如果自旋锁已经被别的进程保持,调用者就轮询(不断的消耗CPU的时间)是否该自旋锁的保持者已经释放了锁("自旋"一词就是因此而得名)。

    三、互斥锁、自旋锁的使用场景:

    1.由于自旋锁使用者一般保持锁时间非常短,因此选择自旋而不是睡眠,自旋锁的效率远高于互斥锁。

    2.自旋锁保持期间是抢占失效的。如果被保护的共享资源需要在中断上下文访问(包括中断上半部和下半部[1]),就必须使用自旋锁。

     

     在ISR中都不能进行进程切换。因为ISR不属于任何进程,而切换只能发生在进程上下文中。虽然ISR在执行过程中要

    使用进程的系统堆栈,但那只是借用,堆栈并不属于isr,而是属于进程。  http://www.chinaunix.net/old_jh/4/902033.html

     

    通常32位Linux内核,进程地址空间划分0~3G为用户空间,3~4G为内核空间。内核空间中的内核代码、数据,为所有进程共享,由MMU映射在相同的物理内存地址。

     

     

      进程进入内核态后,内核代码所使用的栈并不是用户空间中的栈,而是内核空间的栈,进程的“内核栈”。

     

    [1]?怎么理解“中断运行在中断上下文,没有一个所谓的中断描述符来描述它,它不是操作系统调度的单位。一旦在中断上下文中睡眠,首先无法切换上下文(因为没有中断描述符,当前上下文的状态得不到保存),其次,没有人来唤醒它,因为它不是操作系统的调度单位。 ”


    http://www.cnblogs.com/wenxuanguan/p/3897722.html


    ==============================================================================

    上下文切换开销

    进程切换

    进行进程切换就是从正在运行的进程中收回处理器,然后再使待运行进程来占用处理器。 这里所说的从某个进程收回处理器,实质上就是把进程存放在处理器 的寄存器中的中间数据找个地方存起来,从而把处理器的寄存器腾出来让其他进程使用。那么被中止运行进程的中间数据存在何处好呢?当然这个地方应该是进程的 私有堆栈。   

    让进程来占用处理器,实质上是把某个进程存放在私有堆栈中寄存器的数据(前一次本进程被中止时的中间数据)再恢复到处理器的寄存器中去,并把待运行进程的断点送入处理器的程序指针PC,于是待运行进程就开始被处理器运行了,也就是这个进程已经占有处理器的使用权了。   

    这就像多个同学要分时使用同一张课桌一样,说是要收回正在使用课桌同学的课桌使用权,实质上就是让他把属于他的东西拿走;而赋予某个同学课桌使用权,只不过就是让他把他的东西放到课桌上罢了。   

    在切换时,一个进程存储在处理器各寄存器中的中间数据叫做进程的上下文,所以进程的切换实质上就是被中止运行进程与待运行进程上下文的切换。在进程未占用处理器时,进程 的上下文是存储在进程的私有堆栈中的。  

    从上面的叙述可知,调度器进程切换的代码应有如下功能:   

    ●保存处理器PC寄存器的值到被中止进程的私有堆栈;  

    ●保存处理器PSW寄存器的值到被中止进程的私有堆栈;  

    ●保存处理器SP寄存器的值到被中止进程的进程控制块; 

    ●保存处理器其他寄存器的值到被中止进程的私有堆栈; 

    ●自待运行进程的进程控制块取SP值并存入处理器的寄存器SP;  

    ●自待运行进程的私有堆栈恢复处理器各寄存器的值;   

    ●自待运行进程的私有堆栈中弹出PSW值并送入处理器的PSW;

    ●自待运行进程的私有堆栈中弹出PC值并送入处理器的PC。 

      显然,进程的切换可以用中断技术来实现,即当调度器获得了待运行进程的控制块之后,应立即用软 中断指令来中止当前进程的运行,并保存当前进程的PC值和PSW值。其后,使 用压栈指令把处理器其他寄存器的值压入进程私有堆栈。接下来,就从待运行进程的进程控 制块中取出私有堆栈指针的值并存入处理器的寄存器SP,至此SP就指向了待运行进程的私 有堆栈,于是下面就自待运行进程的私有堆栈中弹出上下文进人处理器。最后,利用中断返回指令来实现自待运行进程的私有堆栈中弹出PSW值和自待运行进程的 私有堆栈中弹出PC值的功能。   

    这是一个完整的软中断处理过程,只不过在保护现场和恢复现场工作中,保护的是被中止 运行进程的现场,恢复的是待运行进程的现场,这一切都依赖于堆栈指针的切换。

    进程调度

    1:进程类型:

    在Linux调度算法中,将进程分为两种类型。即:I/O消耗型和CPU消耗型。例如文本处理程序与正在执行的Make的程序。文本处理程序大部份时间都 在等待I/O设备的输入,而make程序大部份时间都在CPU的处理上。因此为了提高响应速度,I/O消耗程序应该有较高的优先级,才能提高它的交互性。 相反的,Make程序相比之下就不那么重要了。只要它能处理完就行了。因此,基于这样的原理,linux有一套交互程序的判断机制。

    在task_struct结构中新增了一个成员:sleep_avg.此值初始值为100。进程在CPU上执行时,此值减少。当进程在等待时,此值增加。最后,在调度的时候。根据sleep_avg的值重新计算优先级。

    2:进程优先级

    正如我们在上面所说的:交互性强的需要高优先级,交互性弱的需要低优先级。在linux系统中,有两种优先级:普通优先级和实时优先级。

    3:运行时间片

    进程的时间片是指进程在抢占前可以持续运行的时间。在linux中,时间片长短可根据优先级来调度。进程不一定要一次运行完所有的时间片,可以在运时的中途被切换出去。

    4:进程抢占

    当一个进程被设为TASK_RUNING状态时。它会判断它的优先级是否高于正在运行的进程。如果是,则设置调度标志位,调用schedule()执行进程的调度。当一个进程的时间片为0时,也会执行进程抢占。


     

    关于CPU,有3个重要的概念:上下文切换(context switchs),运行队列(Run queue)和使用率(utilization)。

    上下文切换:
       目前流行的CPU在同一时间内只能运行一个线程,超线程的处理器可以在同一时间运行多个线程(包括多核CPU),Linux内核会把多核的处理器当作多个单独的CPU来识别。
       一个标准的Linux内核可以支持运行50~50000个进程运行,对于普通的CPU,内核会调度和执行这些进程。每个进程都会分到CPU的时间片来运 行,当一个进程用完时间片或者被更高优先级的进程抢占后,它会备份到CPU的运行队列中,同时其他进程在CPU上运行。这个进程切换的过程被称作上下文切 换。过多的上下文切换会造成系统很大的开销。

    运行队列
      每个CPU都会维持一个运行队列,理想情况下,调度器会不断让队列中的进程运行。进程不是处在sleep状态就是run able状态。如果CPU过载,就会出现调度器跟不上系统的要求,导致可运行的进程会填满队列。队列愈大,程序执行时间就愈长。


    关于时间片和动态优先级
       时间片对于CPU来说是很关键的参数,如果时间片太长,就会使系统的交互性能变差,用户感觉不到并行。如果太短,又会造成系统频繁的上下文切换,使性能 下降。对于IO Bound的系统来讲并不需要太长的时间片,因为系统主要是IO操作;而对于CPU Bound的系统来说需要长的时间片以保持cache的有效性。
      每一个进程启动的时候系统都会给出一个默认的优先级,但在运行过程中,系统会根据进程的运行状况不断调整优先级,内核会升高或降低进程的优先级(每次增加或降低5),判断标准是根据进程处于sleep状态的时间。
      
       IO Bound进程大部分时间在sleep状态,所以内核会调高它的优先级,CPU Bound进程会被内核惩罚降低优先级。因此,如果一个系统上即运行IO Bound进程,又运行CPU Bound进程,会发现,IO Bound进程的性能不会下降,而CPU Bound进程性能会不断下降。

    经验总结:
    1. 对于每一个CPU来说运行队列不要超过2,例如,如果是双核CPU就不要超过4;
    2. 如果CPU在满负荷运行,应该符合下列分布,
    a) User Time:65%~70%
    b) System Time:30%~35%
    c) Idle:0%~5%
    3. 对于上下文切换要结合CPU使用率来看,如果CPU使用满足上述分布,大量的上下文切换也是可以接受的。

    =============================================================================================================

    寄存器

    CPU的基本组成 

    控制器:

           由程序计数器、指令寄存器、指令译码器、时序产生器和操作控制器组成,它是发布命令的“决策机构”,即完成协调和指挥整个计算机系统的操作。它的主要功能有:
    (1)从内存中取出一条指令,并指出下一条指令在内存中的位置;
    (2)对指令进行译码或测试,并产生相应的操作控制信号,以便启动规定的动作;
    (3)指挥并控制CPU、内存和输入/输出设备之间数据流动的方向。

    运算器:

           由算术逻辑单元(ALU)、累加寄存器、数据缓冲寄存器和状态条件寄存器组成,它是数据加工处理部件。相对控制器而言,运算器接受控制器的命令而进行动作 ,即运算器所进行的全部操作都是由控制器发出的控制信号来指挥的,所以它是执行部件。 运算器有两个主要功能:
    (1)执行所有的算术运算;
    (2)执行所有的逻辑运算,并进行逻辑测试,如零值测试或两个值的比较。

    CPU中的主要寄存器

    1.数据缓冲寄存器(DR)

          数据缓冲寄存器用来暂时存放由内存储器读出的一条指令或一个数据字;反之,当向内存存入一条指令或一个数据字时,也暂时将它们存放在数据缓冲寄存器中。

    缓冲寄存器的作用是 :
    (1)作为CPU和内存、外部设备之间信息传送的中转站;
    (2)补偿CPU和内存、外围设备之间在操作速度上的差别;
    (3)在单累加器结构的运算器中,数据缓冲寄存器还可兼作为操作数寄存器。

    2.指令寄存器(IR)

          指令寄存器用来保存当前正在执行的一条指令。当执行一条指令时,先把它从内存取到缓冲寄存器中,然后再传送至指令寄存器。指令划分为操作码和地址码字段,由二进制数字组成。为了执行任何给定的指令,必须对操作码进行测试,以便识别所要求的操作。 指令译码器就是做这项工作的。指令寄存器中操作码字段的输出就是指令译码器的输入。操作码一经译码后,即可向操作控制器发出具体操作的特定信号。

    3.程序计数器(PC)

           为了保证程序能够连续地执行下去,CPU必须具有某些手段来确定下一条指令的地址。而程序计数器正是起到这种作用,所以通常又称为指令计数器。在程序开始执行前,必须将它的起始地址,即程序的一条指令所在的内存单元地址送入PC,因此PC的内容即是从内存提取的第一条指令的地址。当执行指令时,CPU将自动修改PC的内容,以便使其保持的总是将要执行的下一条指令的地址。由于大多数指令都是按顺序来执行的,所以修改的过程通常只是简单的对PC加1。
      但是,当遇到转移指令如JMP指令时,那么后继指令的地址(即PC的内容)必须从指令的地址段取得。在这种情况下,下一条从内存取出的指令将由转移指令来规定,而不是像通常一样按顺序来取得。因此程序计数器的结构应当是具有寄存信息和计数两种功能的结构。

    4.地址寄存器(AR)

            地址寄存器用来保存当前CPU所访问的内存单元的地址。由于在内存和CPU之间存在着操作速度上的差别,所以必须使用地址寄存器来保持地址信息,直到内存的读/写操作完成为止 。
      当CPU和内存进行信息交换,即CPU向内存存/取数据时,或者CPU从内存中读出指令时,都要使用地址寄存器和数据缓冲寄存器。同样,如果我们把外围设备的设备地址作为像内存的地址单元那样来看待,那么,当CPU和外围设备交换信息时,我们同样使用 地址寄存器和数据缓冲寄存器。
      地址寄存器的结构和数据缓冲寄存器、指令寄存器一样,通常使用单纯的寄存器结构。信息的存入一般采用电位-脉冲方式,即电位输入端对应数据信息位,脉冲输入端对应控制信号,在控制信号作用下,瞬时地将信息打入寄存器。

    5.累加寄存器(AC)

     累加寄存器AC通常简称为累加器,它是一个通用寄存器。其功能是:当运算器的算术逻辑单元ALU)执行算术或逻辑运算时,为ALU提供一个工作区。累加寄存器暂时存放ALU运算的结果信息。显然,运算器中至少要有一个累加寄存器。
      目前CPU中的累加寄存器,多达16个,32个,甚至更多。当使用多个累加器时,就变成通用寄存器堆结构,其中任何一个可存放源操作数,也可存放结果操作数。在这种情况下,需要在指令格式中对寄存器号加以编址。

    6.状态条件寄存器(PSW)

           状态条件寄存器保存由算术指令和逻辑指令运行或测试的结果建立的各种条件码内容,如运算结果进位标志(C),运算结果溢出标志(V),运算结果为零标 志(Z),运算结果为负标志(N)等等。这些标志位通常分别由 1位触发器保存。
      除此之外,状态条件寄存器还保存中断和系统工作状态等信息,以便使CPU和系统能及时了解机器运行状态和程序运行状态。因此,状态条件寄存器是一个由各种状态条件标志拼凑而成的寄存器。



    展开全文
  • 用户态和系统态的三种切换方式用户态和系统态切换耗时原因:用户态和系统态切换时寄存器简单变化: 定义: 用户态指非特权状态。在此状态下,执行的代码被硬件限定,不能进行某些操作,比如写入其他进程的存储空间,以...
  • cpu权限被分为两种:内核态和用户态,如果需要调用内核接口就需要内核态权限,称为系统调用。系统调用就是操作系统内部定义的一些函数。 用户级线程和内核级线程 用户级线程 用户级线程由应用级别的线程库进行生成和...
  • 前言 为什么用多线程或多进程? 程序的大部分耗时在等待IO上,瓶颈不在CPU上时,可以提高CPU利用率 需要集中快速处理大量数据,并且不受先后顺序影响 评论区还可补充ing ...不需要用户态/内核态切换,速...
  • 从宏观上来看,Linux操作系统的体系架构分为用户态和内核态(或者用户空间和内核)。内核从本质上看是一种软件,它控制计算机的硬件资源,并提供上层应用程序运行的环境。用户态即上层应用程序的活动空间,应用程序...
  • 目录基本概念线程模型多对一模型一对一模型多对多模型并发上的区别 参考文章 线程的3种实现方式–内核级...由于线程在进程内部的切换规则要比进程的调度简单,所以不需要用户态内核态切换开销,速度快。但缺点
  • 内核线程只运行在内核态,不受用户态上下文的拖累。 处理器竞争:可以在全系统范围内竞争处理器资源; 使用资源:唯一使用的资源是内核栈上下文切换时保持寄存器的空间 调度:调度的开销可能进程自身差不多...
  • 内核线程只运行在内核态,不受用户态上下文的拖累。 Ø 处理器竞争:可以在全系统范围内竞争处理器资源; Ø 使用资源:唯一使用的资源是内核栈上下文切换时保持寄存器的空间 Ø 调度:调度的开销可能进程...
  • 内核线程只运行在内核态,不受用户态上下文的拖累。 处理器竞争:可以在全系统范围内竞争处理器资源;使用资源:唯一使用的资源是内核栈上下文切换时保持寄存器的空间调度:调度的开销可能进程自身差不多昂贵...
  • 由于需要在用户态和内核态之间切换,系统调用的开销相对要大一些。  strace这个工具可以在运行时跟踪程序使用系统调用的情况,这对于我们分析和调试程序的运行行为很有帮助。它的使用也很简单,只要在你运行的...
  • 尽量缩小共享对象的加锁范围,减少锁本身出现竞态条件的概率(导致内核态和用户态切换的时间开销)。 尽量避免把本无逻辑依赖关系的共享对象关联起来(例如把对象纳入某些种类的容器中),这是因为统一操作关联后...
  • 进程切换与模式切换

    2021-06-06 22:26:16
    用户程序相关联的处理器执行模式(用户模式)与操作系统相关联的处理器模式(内核模式)之间的切换, 进程切换必须在操作系统的内核模式下进行 模式切换与进程切换的理解 模式切换可在不改变运行进程状态的...
  • goroutine实际上是运行在线程池上的,由go的runtime实现调度,goroutine调度时,由于不需要像线程一样涉及到系统调用,要进行用户态和内核态切换,因此,goroutine被称为轻量级的线程,开销...
  • 1. 什么是协程 简单可以理解为理解为用户态线程,在学过操作...协程:我们可以简单的理解为用户态线程,避免了内核态和用户态之间的切换来减少线程上下文切换开销。 但是JVM原生是不支持这样的操作的。因此如果...
  • 线程: 同一个进程的各个线程是共享代码和数据空间的,因此线程之间切换开销较小,但是切换需要在用户态和内核态之间,因此就有了协程; 协程: 轻量级线程,涉及到的是函数的切换,协程不是由操作系统内核所管理...
  • 进程是由内核管理调度的,所以进程的切换只能发生在内核态。所以,进程的上下文切换不仅包含了虚拟内存、栈、全局变量等用户空间的资源,还包括了内核堆栈、寄存器等内核空间的资源。 大家需要注意,进程的上下文...
  • 《操作系统》总结

    2020-07-06 15:20:49
    用户态内核态切换(快手) 系统调用 异常 外围设备的中断 二、进程管理 1. 进程线程的区别(爱奇艺) 调度 资源 开销 关系 2. 协程(腾讯) 3. 进程死锁(流利说) 什么是死锁 死锁必要条件 互斥条件 不可抢占...
  • 协程的优点(Python)

    2018-12-18 18:01:00
    协程的优点:协程是进程和线程的升级版,进程和线程都面临着内核态和用户态切换问题而耗费许多切换时间,而协程就是用户自己控制切换的时机,不再需要陷入系统的内核态。协程的执行效率非常高。因为子程序切换不是...
  • python中协程的优点

    2018-11-27 11:11:03
    (1)进程和线程都面临着内核态和用户态切换问题而耗费许多切换时间,而协程就是用户自己控制切换的时机,不再需要陷入系统的内核态。 协程的执行效率非常高。因为子程序切换不是线程切换,而是由程序自身控制。因此...
  • 说明: 协程是进程和线程的升级版,进程和线程都面临着内核态和用户态切换问题而耗费许多切换时间, 而协程就是用户自己控制切换的时机,不再需要陷入系统的内核态。优点: 1. 协程的执行效率非常高。因为子程序...
  • 自旋锁如果持有锁的线程能在很短时间内释放锁资源,那么那些等待竞争锁的线程就不需要做内核态和用户态之间的切换进入阻塞挂起状态,只需让线程执行一个忙循环(自旋),等持有锁的线程释放锁后即可立即获取锁,这样...
  • OS and Database

    2020-05-27 21:57:53
    OS ...操作系统为什么要分用户态和内核态 用户态和内核态的理解和区别 进程和线程切换开销 线程安全是什么 如何实现线程安全 堆区和栈区的区别 协程 银行家算法 银行家算法2 内存映射 内存对齐 ...

空空如也

空空如也

1 2 3 4 5 6
收藏数 114
精华内容 45
关键字:

内核态和用户态切换开销