精华内容
下载资源
问答
  • 用户态和内核态

    2019-10-28 10:21:48
    但是在看之前要先明白操作系统中的用户态和内核态。 值得注意的是Java中的NIO并不是非阻塞式IO(NoneBlocking IO),而是多路复用IO(New IO)。 用户态和内核态 用户态字面理解就是用户使用的...

    前言

    学了C++后发现之前对Java中NIO的理解还是太片面了,所以现在开始更加深入的去学习系统中的IO。学习IO的所有模型可以戳这篇10分钟看懂, Java NIO 底层原理。但是在看之前要先明白操作系统中的用户态和内核态。

    值得注意的是Java中的NIO并不是非阻塞式IO(NoneBlocking IO),而是多路复用IO(New IO)。

    用户态和内核态

    用户态字面理解就是用户使用的空间,内核态则是操作系统使用的空间。在IO中(文件IO或者是网络IO),都是由用户去调用Read读取内核态中的数据,读取数据到用户态;而write则是将数据从用户态写到内核态中,由内核去写入文件或者是通过网络IO(网卡)发送数据。

    下图是Linux系统中的用户态和内核态空间分配。

    1.特权级的概念

    在具体的解释用户态和内核态之前,要先解释一下特权级的概念,简单的理解就是超级会员有普通会员的权限。

    对于任何操作系统来说,创建一个进程是核心功能。创建进程要做很多工作,会消耗很多物理资源。比如分配物理内存,父子进程拷贝信息,拷贝设置页目录页表等等,这些工作得由特定的进程去做,所以就有了特权级别的概念。最关键的工作必须交给特权级最高的进程去执行,这样可以做到集中管理,减少有限资源的访问和使用冲突。inter x86架构的cpu一共有四个级别,0-3级,0级特权级最高,3级特权级最低。

    2.用户态和内核态核心概念

    当一个进程在执行用户自己的代码时处于用户运行态(用户态),此时特权级最低,为3级,是普通的用户进程运行的特权级,大部分用户直接面对的程序都是运行在用户态。Ring3状态不能访问Ring0的地址空间,包括代码和数据;当一个进程因为系统调用陷入内核代码中执行时处于内核运行态(内核态),此时特权级最高,为0级。执行的内核代码会使用当前进程的内核栈,每个进程都有自己的内核栈。

    用户运行一个程序,该程序创建的进程开始时运行自己的代码,处于用户态。如果要执行文件操作、网络数据发送等操作必须通过write、send等系统调用,这些系统调用会调用内核的代码。进程会切换到Ring0,然后进入3G-4G中的内核地址空间去执行内核代码来完成相应的操作。内核态的进程执行完后又会切换到Ring3,回到用户态。这样,用户态的程序就不能随意操作内核地址空间,具有一定的安全保护作用。这说的保护模式是指通过内存页表操作等机制,保证进程间的地址空间不会互相冲突,一个进程的操作不会修改另一个进程地址空间中的数据。

    3.用户态和内核态的切换

    当在系统中执行一个程序时,大部分时间是运行在用户态下的,在其需要操作系统帮助完成一些用户态自己没有特权和能力完成的操作时就会切换到内核态。

    4.用户态切换到内核态的3种方式

    (1)系统调用

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

    (2)异常

    当cpu在执行运行在用户态下的程序时,发生了一些没有预知的异常,这时会触发由当前运行进程切换到处理此异常的内核相关进程中,也就是切换到了内核态,如缺页异常。

    (3)外围设备的中断

    当外围设备完成用户请求的操作后,会向CPU发出相应的中断信号,这时CPU会暂停执行下一条即将要执行的指令而转到与中断信号对应的处理程序去执行,如果前面执行的指令时用户态下的程序,那么转换的过程自然就会是 由用户态到内核态的切换。如硬盘读写操作完成,系统会切换到硬盘读写的中断处理程序中执行后边的操作等。

    这三种方式是系统在运行时由用户态切换到内核态的最主要方式,其中系统调用可以认为是用户进程主动发起的,异常和外围设备中断则是被动的。从触发方式上看,切换方式都不一样,但从最终实际完成由用户态到内核态的切换操作来看,步骤有事一样的,都相当于执行了一个中断响应的过程。系统调用实际上最终是中断机制实现的,而异常和中断的处理机制基本一致。

    5.用户态到内核态具体的切换步骤

    这方面可以去看这篇文章:Linux内核堆栈使用方法 进程0和进程1

    (1)从当前进程的描述符中提取其内核栈的ss0及esp0信息。

    (2)使用ss0和esp0指向的内核栈将当前进程的cs,eip,eflags,ss,esp信息保存起来,这个过程也完成了由用户栈到内核栈的切换过程,同时保存了被暂停执行的程序的下一条指令。

    (3)将先前由中断向量检索得到的中断处理程序的cs,eip信息装入相应的寄存器,开始执行中断处理程序,这时就转到了内核态的程序执行了。

    参考文章:

    https://blog.csdn.net/qq_39823627/article/details/78736650

    https://www.cnblogs.com/crazymakercircle/p/10225159.html

    https://blog.csdn.net/yihaolovem/article/details/37119971

    展开全文
  • 文章来源于 拉钩教育 重学操作系统 林䭽 用户态和内核态用户态线程和内核态线程有什么区别? 什么是用户态和内核态 Kernel 运行在超级权限模式(Supervisor Mode)下,所以拥有很高的权限。按照权限管理的原则,...

    转载

    文章来源于 拉钩教育 重学操作系统 林䭽 用户态和内核态:用户态线程和内核态线程有什么区别?

    什么是用户态和内核态

    Kernel 运行在超级权限模式(Supervisor Mode)下,所以拥有很高的权限。按照权限管理的原则,多数应用程序应该运行在最小权限下。因此,很多操作系统,将内存分成了两个区域:

    1. 内核空间(Kernal Space),这个空间只有内核程序可以访问;

    2. 用户空间(User Space),这部分内存专门给应用程序使用。

    用户态和内核态

    用户空间中的代码被限制了只能使用一个局部的内存空间,我们说这些程序在用户态(User Mode) 执行。内核空间中的代码可以访问所有内存,我们称这些程序在内核态(Kernal Mode) 执行。

    系统调用过程

    如果用户态程序需要执行系统调用,就需要切换到内核态执行。下面我们来讲讲这个过程的原理。
    在这里插入图片描述
    如上图所示:内核程序执行在内核态(Kernal Mode),用户程序执行在用户态(User Mode)。当发生系统调用时,用户态的程序发起系统调用。因为系统调用中牵扯特权指令,用户态程序权限不足,因此会中断执行,也就是 Trap(Trap 是一种中断)。

    发生中断后,当前 CPU 执行的程序会中断,跳转到中断处理程序。内核程序开始执行,也就是开始处理系统调用。内核处理完成后,主动触发 Trap,这样会再次发生中断,切换回用户态工作。

    线程模型

    上面我们学习了用户态和内核态,接下来我们从进程和线程的角度进一步思考本课时开头抛出的问题。

    进程和线程

    一个应用程序启动后会在内存中创建一个执行副本,这就是进程。Linux 的内核是一个 Monolithic Kernel(宏内核),因此可以看作一个进程。也就是开机的时候,磁盘的内核镜像被导入内存作为一个执行副本,成为内核进程。

    进程可以分成用户态进程和内核态进程两类。用户态进程通常是应用程序的副本,内核态进程就是内核本身的进程。如果用户态进程需要申请资源,比如内存,可以通过系统调用向内核申请。

    那么用户态进程如果要执行程序,是否也要向内核申请呢?

    程序在现代操作系统中并不是以进程为单位在执行,而是以一种轻量级进程(Light Weighted Process),也称作线程(Thread)的形式执行。

    一个进程可以拥有多个线程。进程创建的时候,一般会有一个主线程随着进程创建而创建。
    在这里插入图片描述
    如果进程想要创造更多的线程,就需要思考一件事情,这个线程创建在用户态还是内核态。

    你可能会问,难道不是用户态的进程创建用户态的线程,内核态的进程创建内核态的线程吗?

    其实不是,进程可以通过 API 创建用户态的线程,也可以通过系统调用创建内核态的线程,接下来我们说说用户态的线程和内核态的线程。

    用户态线程

    用户态线程也称作用户级线程(User Level Thread)。操作系统内核并不知道它的存在,它完全是在用户空间中创建。

    用户级线程有很多优势,比如。

    1. 管理开销小:创建、销毁不需要系统调用。

    2. 切换成本低:用户空间程序可以自己维护,不需要走操作系统调度。

    但是这种线程也有很多的缺点。

    1. 与内核协作成本高:比如这种线程完全是用户空间程序在管理,当它进行 I/O 的时候,无法利用到内核的优势,需要频繁进行用户态到内核态的切换。

    2. 线程间协作成本高:设想两个线程需要通信,通信需要 I/O,I/O 需要系统调用,因此用户态线程需要支付额外的系统调用成本。

    3. 无法利用多核优势:比如操作系统调度的仍然是这个线程所属的进程,所以无论每次一个进程有多少用户态的线程,都只能并发执行一个线程,因此一个进程的多个线程无法利用多核的优势。

    4. 操作系统无法针对线程调度进行优化:当一个进程的一个用户态线程阻塞(Block)了,操作系统无法及时发现和处理阻塞问题,它不会更换执行其他线程,从而造成资源浪费。

    内核态线程

    内核态线程也称作内核级线程(Kernel Level Thread)。这种线程执行在内核态,可以通过系统调用创造一个内核级线程。

    内核级线程有很多优势。

    1. 可以利用多核 CPU 优势:内核拥有较高权限,因此可以在多个 CPU 核心上执行内核线程。

    2. 操作系统级优化:内核中的线程操作 I/O 不需要进行系统调用;一个内核线程阻塞了,可以立即让另一个执行。

    当然内核线程也有一些缺点。

    1. 创建成本高:创建的时候需要系统调用,也就是切换到内核态。

    2. 扩展性差:由一个内核程序管理,不可能数量太多。

    3. 切换成本较高:切换的时候,也同样存在需要内核操作,需要切换内核态。

    用户态线程和内核态线程之间的映射关系

    线程简单理解,就是要执行一段程序。程序不会自发的执行,需要操作系统进行调度。我们思考这样一个问题,如果有一个用户态的进程,它下面有多个线程。如果这个进程想要执行下面的某一个线程,应该如何做呢?

    这时,比较常见的一种方式,就是将需要执行的程序,让一个内核线程去执行。毕竟,内核线程是真正的线程。因为它会分配到 CPU 的执行资源。

    如果一个进程所有的线程都要自己调度,相当于在进程的主线程中实现分时算法调度每一个线程,也就是所有线程都用操作系统分配给主线程的时间片段执行。这种做法,相当于操作系统调度进程的主线程;进程的主线程进行二级调度,调度自己内部的线程。

    这样操作劣势非常明显,比如无法利用多核优势,每个线程调度分配到的时间较少,而且这种线程在阻塞场景下会直接交出整个进程的执行权限。

    由此可见,用户态线程创建成本低,问题明显,不可以利用多核。内核态线程,创建成本高,可以利用多核,切换速度慢。因此通常我们会在内核中预先创建一些线程,并反复利用这些线程。这样,用户态线程和内核态线程之间就构成了下面 4 种可能的关系:

    多对一(Many to One)
    用户态进程中的多线程复用一个内核态线程。这样,极大地减少了创建内核态线程的成本,但是线程不可以并发。因此,这种模型现在基本上用的很少。我再多说一句,这里你可能会有疑问,比如:用户态线程怎么用内核态线程执行程序?

    程序是存储在内存中的指令,用户态线程是可以准备好程序让内核态线程执行的。后面的几种方式也是利用这样的方法。
    在这里插入图片描述
    一对一(One to One)

    该模型为每个用户态的线程分配一个单独的内核态线程,在这种情况下,每个用户态都需要通过系统调用创建一个绑定的内核线程,并附加在上面执行。 这种模型允许所有线程并发执行,能够充分利用多核优势,Windows NT 内核采取的就是这种模型。但是因为线程较多,对内核调度的压力会明显增加。
    在这里插入图片描述
    多对多(Many To Many)
    这种模式下会为 n 个用户态线程分配 m 个内核态线程。m 通常可以小于 n。一种可行的策略是将 m 设置为核数。这种多对多的关系,减少了内核线程,同时也保证了多核心并发。Linux 目前采用的就是该模型。
    在这里插入图片描述
    两层设计(Two Level)
    这种模型混合了多对多和一对一的特点。多数用户态线程和内核线程是 n 对 m 的关系,少量用户线程可以指定成 1 对 1 的关系。
    在这里插入图片描述
    上图所展现的是一个非常经典的设计。

    我们这节课讲解的问题、考虑到的情况以及解决方法,将为你今后解决实际工作场景中的问题打下坚实的基础。比如处理并发问题、I/O 性能瓶颈、思考数据库连接池的配置等,要想完美地解决问题,就必须掌握这些模型,了解问题的本质上才能更好地思考问题衍生出来的问题。

    用户态线程和内核态线程的区别?

    用户态线程工作在用户空间,内核态线程工作在内核空间。用户态线程调度完全由进程负责,通常就是由进程的主线程负责。相当于进程主线程的延展,使用的是操作系统分配给进程主线程的时间片段。内核线程由内核维护,由操作系统调度。

    用户态线程无法跨核心,一个进程的多个用户态线程不能并发,阻塞一个用户态线程会导致进程的主线程阻塞,直接交出执行权限。这些都是用户态线程的劣势。内核线程可以独立执行,操作系统会分配时间片段。因此内核态线程更完整,也称作轻量级进程。内核态线程创建成本高,切换成本高,创建太多还会给调度算法增加压力,因此不会太多。

    实际操作中,往往结合两者优势,将用户态线程附着在内核态线程中执行。

    展开全文
  • 用户态和内核态的区别.pdf
  • 1、用户态和内核态的区别? 明白这两个概念之前,我们得知道用户空间和内核空间。 用户空间:指的就是用户可以操作和访问的空间,这个空间通常存放我们用户自己写的数据等。 内核空间:是系统内核来操作的一块...

    1、用户态和内核态的区别?

    明白这两个概念之前,我们得知道用户空间内核空间

    用户空间:指的就是用户可以操作和访问的空间,这个空间通常存放我们用户自己写的数据等。

    内核空间:是系统内核来操作的一块空间,这块空间里面存放系统内核的函数、接口等。

    在用户空间下执行,我们把此时运行得程序的这种状态成为用户态,而当这段程序执行在内核的空间执行时,这种状态称为内核态。

    当一个任务(进程)执行系统调用而陷入内核代码中执行时,我们就称进程处于内核状态。此时处理器处于特权级最高的(0级)内核代码。当进程处于内核态时,执行的内核代码会使用当前的内核栈。每个进程都有自己的内核栈。

    当进程在执行用户自己的代码时,则称其处于用户态。即此时处理器在特权级最低的用户代码中运行。当正在执行用户程序而突然中断时,此时用户程序也可以象征性地处于进程的内核态。因为中断处理程序将使用当前进程的内核态。

    延伸阅读:内核态与用户态是操作系统的两种运行级别,跟intel cpu没有必然联系,intel cpu提供Ring0-Ring3三种级别运行模式,Ring0级别最高,Ring3级别最低。Linux使用了Ring3级别运行用户态。Ring0作为内核态,没有使用Ring1和Ring2.Ring3不能访问Ring0的地址空间,包括代码和数量。Linux进程的4GB空间,3G-4G这1G部分大家是共享的,是内核态的地址空间,这里存放在整个内核代码和所有的内核模块,以及内核所维护的数据。用户运行一程序,该程序所创建的进程开始是运行在用户态的,如果要执行文件操作,网络数据发送等操作,必须通过write,send等系统调用,这些系统会调用内核中的代码来完成操作,这时,必须切换到Ring0,然后进入1G的内核地址空间去执行这些代码完成操作,完成后,切换Ring3,回到用户态。这样,用户态的程序就不能随意操作内核地址空间,具有一定的安全保护作用。

    2、用户态和内核态的转换

    用户态切换到内核态的3种方式:a.系统调用 b.异常  c.外围设备的中断

    a.系统调用

    这是用户进程主动要求切换到内核态的一种方式,用户进程通过系统调用申请操作系统提供的服务程序完成工作。

    而系统调用的机制其核心还是使用了操作系统为用户特别开放的一个中断来实现,该中断是程序人员自己开发出的一种正常的异常,这个异常具体就是调用int $0x80的汇编指令,这条汇编指令将产生向量为0x80的编程异常。(软中断)

    b.异常
    当CPU在执行运行在用户态的程序时,发现了某些事件不可知的异常,这是会触发由当前运行进程切换到处理此
    异常的内核相关程序中,也就到了内核态,比如缺页异常(硬中断)。

    c.外围设备的中断
    当外围设备完成用户请求的操作之后,会向CPU发出相应的中断信号,这时CPU会暂停执行下一条将要执行的指令
    转而去执行中断信号的处理程序,如果先执行的指令是用户态下的程序,那么这个转换的过程自然也就发生了有
    用户态到内核态的切换。比如硬盘读写操作完成,系统会切换到硬盘读写的中断处理程序中执行后续操作等。

    以系统调用函数open为例:简单图示

    (1)用户态:

    ① 触发0x80中断

    ②保存当前的运行位置,状态,数据

    ③将系统调用号保存到eax寄存器中

    触发0x80中断 由系统调用函数触发的中断 。实际上在内核中,  触发0x80中断之后才会有上面的两步 。

    (2)每一个中断号在内核中都有一个中断处理程序,中断处理程序是被内核调用来响应中断的

              通过该中断处理程序陷入内核

    (3)在内核中:①有系统调用表,用寄存器中的系统调用号对应一个系统调用函数

                              ②通过函数得到执行该系统调用函数会得到一个返回值fd

                              ③将fd的值用eax寄存器带出  

    在函数调用时int fd=open();open调用完之后才会将eax中的得到的返回值赋给fd,相当于是两个步骤

    只有0x80中断才是系统调用中断,类似的还有缺页中断它们所对应的中断号是不同的

    注释:在c语言中如何返回返回值:如果返回值小于四个字节通过eax寄存器带出  若在4-8之间用eax和ecx带出  大于8通过生成临时对象或者变量带出


     

     

    展开全文
  • 线程用户态和内核态

    千次阅读 2019-05-14 13:59:52
    (1)用户态和内核态的概念? —>内核态: CPU可以访问内存所有数据, 包括外围设备, 例如硬盘, 网卡. CPU也可以将自己从一个程序切换到另一个程序 —>用户态: 只能受限的访问内存, 且不允许访问外围设备. 占用CPU...

    (1)用户态和内核态的概念?

    —>内核态: CPU可以访问内存所有数据, 包括外围设备, 例如硬盘, 网卡. CPU也可以将自己从一个程序切换到另一个程序
    —>用户态: 只能受限的访问内存, 且不允许访问外围设备. 占用CPU的能力被剥夺, CPU资源可以被其他程序获取

    (2)为什么需要用户态和内核态?
    —>由于需要限制不同的程序之间的访问能力, 防止他们获取别的程序的内存数据, 或者获取外围设备的数据, 并发送到网络, CPU划分出两个权限等级 :用户态 和 内核态

    (3)用户态与内核态的切换?
    所有用户程序都是运行在用户态的, 但是有时候程序确实需要做一些内核态的事情, 例如从硬盘读取数据, 或者从键盘获取输入等. 而唯一可以做这些事情的就是操作系统, 所以此时程序就需要先操作系统请求以程序的名义来执行这些操作.

    这时需要一个这样的机制: 用户态程序切换到内核态, 但是不能控制在内核态中执行的指令

    这种机制叫系统调用, 在CPU中的实现称之为陷阱指令(Trap Instruction)

    他们的工作流程如下:

    用户态程序将一些数据值放在寄存器中, 或者使用参数创建一个堆栈(stack frame), 以此表明需要操作系统提供的服务.
    用户态程序执行陷阱指令
    CPU切换到内核态, 并跳到位于内存指定位置的指令, 这些指令是操作系统的一部分, 他们具有内存保护, 不可被用户态程序访问
    这些指令称之为陷阱(trap)或者系统调用处理器(system call handler). 他们会读取程序放入内存的数据参数, 并执行程序请求的服务
    系统调用完成后, 操作系统会重置CPU为用户态并返回系统调用的结果

    二:用户态和内核态的详细介绍?
    当一个任务(进程)执行系统调用而陷入内核代码中执行时,我们就称进程处于内核运行态(或简称为内核态)。此时处理器处于特权级最高的(0级)内核 代码中执行。当进程处于内核态时,执行的内核代码会使用当前进程的内核栈。每个进程都有自己的内核栈。当进程在执行用户自己的代码时,则称其处于用户运行 态(用户态)。即此时处理器在特权级最低的(3级)用户代码中运行。当正在执行用户程序而突然被中断程序中断时,此时用户程序也可以象征性地称为处于进程 的内核态。因为中断处理程序将使用当前进程的内核栈。这与处于内核态的进程的状态有些类似。

    内核态与用户态是操作系统的两种运行级别, 跟intel cpu没有必然的联系, intel cpu提供Ring0-Ring3三种级别的运行模式,Ring0级别最高,Ring3最低。Linux使用了Ring3级别运行用户态,Ring0作为 内核态,没有使用Ring1和Ring2。Ring3状态不能访问Ring0的地址空间,包括代码和数据。Linux进程的4GB地址空间,3G-4G部 分大家是共享的,是内核态的地址空间,这里存放在整个内核的代码和所有的内核模块,以及内核所维护的数据。用户运行一个程序,该程序所创建的进程开始是运 行在用户态的,如果要执行文件操作,网络数据发送等操作,必须通过write,send等系统调用,这些系统调用会调用内核中的代码来完成操作,这时,必 须切换到Ring0,然后进入3GB-4GB中的内核地址空间去执行这些代码完成操作,完成后,切换回Ring3,回到用户态。这样,用户态的程序就不能 随意操作内核地址空间,具有一定的安全保护作用。
    至于说保护模式,是说通过内存页表操作等机制,保证进程间的地址空间不会互相冲突,一个进程的操作不会修改另一个进程的地址空间中的数据。

    1. 用户态和内核态的概念区别

    究竟什么是用户态,什么是内核态,这两个基本概念以前一直理解得不是很清楚,根本原因个人觉得是在于因为大部分时候我们在写程序时关注的重点和着眼的角度放在了实现的功能和代码的逻辑性上,先看一个例子:

    1)例子

    void testfork(){
    if(0 = = fork()){
    printf(“create new process success!\n”);
    }
    printf(“testfork ok\n”);
    }
    

    这段代码很简单,从功能的角度来看,就是实际执行了一个fork(),生成一个 新的进程,从逻辑的角度看,就是判断了如果fork()返回的是0则打印相关语句,然后函数最后再打印一句表示执行完整个testfork()函数。代码 的执行逻辑和功能上看就是如此简单,一共四行代码,从上到下一句一句执行而已,完全看不出来哪里有体现出用户态和进程态的概念。

    如果说前面两种是静态观察的角度看的话,我们还可以从动态的角度来看这段代码,即它被转换成CPU执行的指令后加载执行的过程,这时这段程序就是一个动态执行的指令序列。而究竟加载了哪些代码,如何加载就是和操作系统密切相关了。

    2)特权级

    熟悉Unix/Linux系统的人都知道,fork的工作实际上是以系统调用的 方式完成相应功能的,具体的工作是由sys_fork负责实施。其实无论是不是Unix或者Linux,对于任何操作系统来说,创建一个新的进程都是属于 核心功能,因为它要做很多底层细致地工作,消耗系统的物理资源,比如分配物理内存,从父进程拷贝相关信息,拷贝设置页目录页表等等,这些显然不能随便让哪 个程序就能去做,于是就自然引出特权级别的概念,显然,最关键性的权力必须由高特权级的程序来执行,这样才可以做到集中管理,减少有限资源的访问和使用冲 突。

    特权级显然是非常有效的管理和控制程序执行的手段,因此在硬件上对特权级做了很 多支持,就Intel x86架构的CPU来说一共有0~3四个特权级,0级最高,3级最低,硬件上在执行每条指令时都会对指令所具有的特权级做相应的检查,相关的概念有 CPL、DPL和RPL,这里不再过多阐述。硬件已经提供了一套特权级使用的相关机制,软件自然就是好好利用的问题,这属于操作系统要做的事情,对于 Unix/Linux来说,只使用了0级特权级和3级特权级。也就是说在Unix/Linux系统中,一条工作在0级特权级的指令具有了CPU能提供的最 高权力,而一条工作在3级特权级的指令具有CPU提供的最低或者说最基本权力。

    3)用户态和内核态

    现在我们从特权级的调度来理解用户态和内核态就比较好理解了,当程序运行在3级 特权级上时,就可以称之为运行在用户态,因为这是最低特权级,是普通的用户进程运行的特权级,大部分用户直接面对的程序都是运行在用户态;反之,当程序运 行在0级特权级上时,就可以称之为运行在内核态。

    虽然用户态下和内核态下工作的程序有很多差别,但最重要的差别就在于特权级的不 同,即权力的不同。运行在用户态下的程序不能直接访问操作系统内核数据结构和程序,比如上面例子中的testfork()就不能直接调用 sys_fork(),因为前者是工作在用户态,属于用户态程序,而sys_fork()是工作在内核态,属于内核态程序。

    当我们在系统中执行一个程序时,大部分时间是运行在用户态下的,在其需要操作系 统帮助完成某些它没有权力和能力完成的工作时就会切换到内核态,比如testfork()最初运行在用户态进程下,当它调用fork()最终触发 sys_fork()的执行时,就切换到了内核态。

    2. 用户态和内核态的转换

    1)用户态切换到内核态的3种方式

    a. 系统调用

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

    b. 异常

    当CPU在执行运行在用户态下的程序时,发生了某些事先不可知的异常,这时会触发由当前运行进程切换到处理此异常的内核相关程序中,也就转到了内核态,比如缺页异常。

    c. 外围设备的中断

    当外围设备完成用户请求的操作后,会向CPU发出相应的中断信号,这时CPU会 暂停执行下一条即将要执行的指令转而去执行与中断信号对应的处理程序,如果先前执行的指令是用户态下的程序,那么这个转换的过程自然也就发生了由用户态到 内核态的切换。比如硬盘读写操作完成,系统会切换到硬盘读写的中断处理程序中执行后续操作等。

    这3种方式是系统在运行时由用户态转到内核态的最主要方式,其中系统调用可以认为是用户进程主动发起的,异常和外围设备中断则是被动的。

    2)具体的切换操作

    从触发方式上看,可以认为存在前述3种不同的类型,但是从最终实际完成由用户态 到内核态的切换操作上来说,涉及的关键步骤是完全一致的,没有任何区别,都相当于执行了一个中断响应的过程,因为系统调用实际上最终是中断机制实现的,而 异常和中断的处理机制基本上也是一致的,关于它们的具体区别这里不再赘述。关于中断处理机制的细节和步骤这里也不做过多分析,涉及到由用户态切换到内核态 的步骤主要包括:

    [1] 从当前进程的描述符中提取其内核栈的ss0及esp0信息。

    [2] 使用ss0和esp0指向的内核栈将当前进程的cs,eip,eflags,ss,esp信息保存起来,这个

    过程也完成了由用户栈到内核栈的切换过程,同时保存了被暂停执行的程序的下一

    条指令。

    [3] 将先前由中断向量检索得到的中断处理程序的cs,eip信息装入相应的寄存器,开始

    执行中断处理程序,这时就转到了内核态的程序执行了。

    补充:
    线程的上下文切换:
    CPU通过时间片段的算法来循环执行线程任务,而循环执行即每个线程允许运行的时间后的切换,而这种循环的切换使各个程序从表面上看是同时进行的。而切换时会保存之前的线程任务状态,当切换到该线程任务的时候,会重新加载该线程的任务状态。而这个从保存到加载的过程称之为上下文切换。

    • 若当前线程还在运行而时间片结束后,CPU将被剥夺并分配给另一个线程。
    • 若线程在时间片结束前阻塞或结束,CPU进行线程切换。而不会造成CPU资源浪费。

    因此线程切换是多个线程之间的操作,而线程核心态和用户态切换是一个线程执行时对于CPU使用的不同状态

    展开全文
  • linux用户态和内核态

    千次阅读 2020-10-24 10:43:52
    内核态和用户态 对于linux中的内核态和用户态之间的关联,我觉得下面的图片很形象 该图片来源于:https://www.cnblogs.com/bakari/p/5520860.html 如上图所示,从宏观上来看,Linux操作系统的体系架构分为用户态和...
  • JVM线程用户态和内核态 一. 线程用户态和内核态概念 1.1 为什么会有用户态和内核态 由于需要限制不同的程序之间的访问能力, 防止他们获取别的程序的内存数据, 或者获取外围设备的数据, 并发送到网络, CPU划分出两个...
  • 用户态和内核态的区别

    千次阅读 2018-08-30 09:10:25
    用户态和内核态的区别 你是世界的一杆称,一头重一头轻。 –RuiDer --大侄子的纪念日2018-8-27 before 本篇文章是我在学习Java的synchornized锁底层原理时碰到的一个知识点,了解过synchornized底层...
  • 用户态和内核态 中断处理机制

    千次阅读 2021-01-15 22:57:54
    1.1 用户态和内核态 1.1.1 定义:什么是用户态和内核态? Kernel 运行在超级权限模式(Supervisor Mode)下,所以拥有很高的权限。按照权限管理的原则,多数应用程序应该运行在最小权限下。因此,很多操作系统,将...
  • 操作系统基础知识用户态和内核态的区别.pdf
  • Linux下用户态和内核态内存共享的实现.pdf
  • 用户态和内核态之间的切换 切换方式 从用户态内核态切换可以通过三种方式,或者说会导致从用户态切换到内核态的操作: 系统调用,这个上面已经讲解过了,在我公众号之前的文章也有讲解过。其实系统调用本身就是...
  • android 用户态和内核态

    千次阅读 2016-08-05 19:18:48
    android 用户态和内核态
  • java用户态和内核态

    千次阅读 2019-01-06 00:41:40
    这本书上多次看到用户态和内核态两个名词, 虽然大概能明白意思. 但对于两者具体的定义和区别还是比较, 特此查阅之后记录. 内核态(Kernel Mode)与用户态(User Mode) 内核态: CPU可以访问内存所有数据, 包括外围设备...
  • 究竟什么是用户态,什么是内核态,这两个基本概念以前一直理解得不是很清楚,根本原因个人觉得是在于因为大部分时候我们在写程序时关注的重点着眼的角度放在了实现的功能代码的逻辑性上,先看一个例子: ...
  • windows用户态和内核态

    2018-12-03 21:48:25
     用户态和内核态是不同的CPU特权级别,X86用户态为RING3,内核态在RING0。  win32系统可以使用的最大内存空间为4GB,用户态代码可以使用的是0x00000000——0x7FFFFFFF。  从用户态进入核心态最常用方法是将功能...
  • 用户态和内核态的简单理解

    千次阅读 2020-12-12 15:12:18
    文章目录linux基础系统调用和库函数的区别什么是用户态和内核态用户态和内核态的相互转换 linux基础 linux的kernel内核外是系统调用,系统调用外是shell、库函数 系统调用和库函数的区别 内核:屏蔽了调用各硬件...
  • 浅谈Linux用户态和内核态

    千次阅读 2016-09-14 12:03:11
    为什么要分用户态和内核态? 在 CPU 的所有指令中,有一些指令是非常危险的,如果错用,将导致整个系统崩溃。比如:清内存、设置时钟等。如果所有的程序都能使用这些指令,那么你的系统一天死机 n 回就不足为奇了。...
  • 基于系统调用和共享内存的用户态和内核态通信,何华丽,,介绍了Linux内核态用户态过程间实现通信的必要性,并给出Linux系统提供的几种常用内核与用户交换数据的机制。由于这几种机制在大��
  • 要了解什么是用户态,什么是内核态,我们需要先了解什么是进程的用户空间内核空间:Linux虚拟内存的大小为2^32(在32位的x86机器上),内核将这4G字节的空间分为两部分。最高的1G字节(从虚地址0xC0000000到0...
  • 用户态和内核态的切换耗费时间的原因 总的来说,就是线程切换或者加锁解锁都是因为需要用户态和内核态的切换,从而导致的开销大。 应用程序的执行需要依托内核提供的资源,包括CPU、存储、IO等,因此内核提供了一个...
  • 用户态和内核态切换

    千次阅读 2020-12-22 21:30:27
    用户态内核态切换可以通过三种方式,或者说会导致从用户态切换到内核态的操作: 系统调用,这个上面已经讲解过了,在我公众号之前的文章也有讲解过。其实系统调用本身就是中断,但是软件中断,跟硬中断不同。...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 116,244
精华内容 46,497
关键字:

用户态和内核态