精华内容
下载资源
问答
  • 用户态和内核态的区别是什么
    2021-06-19 00:39:02

    用户态和内核态的区别是,内核态运行操作系统程序,操作硬件,用户态运行用户程序;当程序运行在3级特权级上时,可以称之为运行在用户态,当程序运行在0级特权级上时,称之为运行在内核态。

    b059eee653f612b30c0339a0013fac45.png

    本文操作环境:windows10系统、thinkpad t490电脑。

    区别分析如下:

    1.操作系统需要两种CPU状态

    内核态(Kernel Mode):运行操作系统程序,操作硬件

    用户态(User Mode):运行用户程序

    2.指令划分

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

    非特权指令:用户程序可以使用的指令。 举例:控制转移 算数运算 取数指令 访管指令(使用户程序从用户态陷入内核态)

    3.特权级别

    特权环:R0、R1、R2和R3

    R0相当于内核态,R3相当于用户态;

    不同级别能够运行不同的指令集合;

    4.CPU状态之间的转换

    用户态--->内核态:唯一途径是通过中断、异常、陷入机制(访管指令)

    内核态--->用户态:设置程序状态字PSW

    5.内核态与用户态的区别

    内核态与用户态是操作系统的两种运行级别,当程序运行在3级特权级上时,就可以称之为运行在用户态。因为这是最低特权级,是普通的用户进程运行的特权级,大部分用户直接面对的程序都是运行在用户态;

    当程序运行在0级特权级上时,就可以称之为运行在内核态。

    运行在用户态下的程序不能直接访问操作系统内核数据结构和程序。当我们在系统中执行一个程序时,大部分时间是运行在用户态下的,在其需要操作系统帮助完成某些它没有权力和能力完成的工作时就会切换到内核态(比如操作硬件)。

    这两种状态的主要差别是

    处于用户态执行时,进程所能访问的内存空间和对象受到限制,其所处于占有的处理器是可被抢占的处于内核态执行时,则能访问所有的内存空间和对象,且所占有的处理器是不允许被抢占的。

    更多相关内容
  • 实用文案 Linux 内核空间与用户空间通信机制的研究 Linux kernel space and user space communication mechanism 摘 要 标准文档 实用文案 Linux 是一个源码开放的操作系统 无论是普通用户还是企业用户都可以编写...
  • 用户态和内核态

    2020-12-02 00:02:21
    CPU特权级:用户态和内核态用户态进入内核态的方式系统调用异常中断用户态内核态的具体切换过程结语 前言 在本文中,会涉及到中断,异常,系统调用等概念。在有些参考资料上,会将中断和系统调用归为异常的一类...

    title: 用户态和内核态
    date: 2020-12-01 16:49:21
    tags: Linux
    categories: OS


    前言

    在本文中,会涉及到中断,异常,系统调用等概念。在有些参考资料上,会将中断和系统调用归为异常的一类;也有的资料将异常称为软中断,本文采用后者的描述方式。事实上,三者的具体实现机制和处理方式本质上是一致的,因此会出现不同的定义描述方式也无可厚非。

    什么是用户态?什么是内核态?

    问题引入:OS为什么要区分用户态和内核态?

    1. 出于安全的考虑:在操作系统中有一些较危险指令,应交由受信任的内核来完成。(比如涉及到对底层硬件的访问修改操作时)
    2. 出于并发的考虑:如果没有内核态,当一个程序A执行时,该怎么来打断A去执行另一个程序B?答案是无法做到,如果A不主动释放CPU控制权是没有办法去切换进程的,也就无法实现并发。通过中断进入内核态,由内核来实现进程调度。

    用户态和内核态是一个抽象出来的概念,在此具体介绍它们之前先了解下CPU特权级的概念。

    CPU特权级:

    在操作系统中有一些较危险指令,普通用户程序不能随意执行,只能由受信任的内核程序来执行。也就是说内核程序拥有更大的权利即更高的特权级,而普通用户程序特权级较低。在intel x86 CPU架构中,提供了Ring0~Ring3四种特权级,其中Ring0特权级最高。在采用x86架构的Linux系统中,只使用了Ring0和Ring3两个特权级,Ring0特权级对应内核态,Ring3对应用户态

    用户态和内核态

    当程序执行时不涉及访问硬件资源,便处于用户态,当程序主动发起系统调用想要访问硬件资源时,产生异常时或者外部硬件产生中断时,便会进入内核态。结合CPU特权级理解,用户态进行的操作是受限的,而内核态的操作是不受限的。

    从用户态进入内核态的方式

    这里只是从用户态进入内核态的角度简单的介绍了下系统调用、异常、中断,欲了解更多相关知识,请自行查阅资料。

    系统调用

    如果用户程序想要进行一些需要高权限才能实现的操作,比如创建进程、读写文件等操作(底层需要进行硬件资源),该如何实现?操作系统提供了系统调用这一接口,用户程序主动执行“syscall n”指令,n代表n号服务,“syscall n”指令便调用了n号系统调用,这一指令会使得程序trap内陷到内核态,然后将控制转移到对应的n号陷阱处理程序,处理结束后返回到syscall指令的下一条指令。

    异常

    当程序进行一些本不该进行的操作例如除0操作、访问一块不该访问的内存,控制权会转入对应的异常处理程序,即切换到内核态进行处理,处理结束后会重新执行产生异常的指令或者直接终止该程序。

    中断

    当外设硬件设备产生一个中断信号时,CPU发现中断产生,立即转到中断处理程序(中断服务例程),即进入内核态进行处理,处理结束后继续上次被打断的任务。

    用户态、内核态的具体切换过程

    用户态到内核态的实现主要是特权级的转换和用户栈到内核栈的转换。

    用户栈到内核栈的转换大体步骤:

    1. 首先找到内核栈的栈基址和栈顶指针。
    2. 将当前环境的各种状态值压入内核栈。
    3. 将先前由中断向量检索得到的中断处理程序的 cs,ip 信息装入相应的寄存器,开始执行中断处理程序,这时就转到了内核态的程序执行了。(这里的“中断”指的是广义的中断,包括异常和系统调用)

    那么如何具体实现的呢?(下面的内容要求一点内核基础)

    1. 如何找到内核栈的栈基址:linux中task_struct结构中有一thread_info结构,thread_info和内核栈被thread_union紧密包裹在一块,因此可以通过当前进程的task_struct结构体找到thread_info,thread_info 的地址加上thread_union的大小(一般为8k,两个页框)就是内核栈基址。
      在这里插入图片描述

      // 摘自/linux-4.9.229/include/linux/sched.h 第1487行
      struct task_struct {
      #ifdef CONFIG_THREAD_INFO_IN_TASK
      	/*
      	 * For reasons of header soup (see current_thread_info()), this
      	 * must be the first element of task_struct.
      	 */
      	struct thread_info thread_info;
      #endif
      ...
      }
      
      // 摘自/linux-4.9.229/include/linux/sched.h
      union thread_union {
      #ifndef CONFIG_THREAD_INFO_IN_TASK
      	struct thread_info thread_info;
      #endif
      	unsigned long stack[THREAD_SIZE/sizeof(long)];
      };
      
    2. 如何找到内核栈的栈顶指针esp:linux为每一个cpu提供一个tss段,并且在tr寄存器中保存该段。为了便于理解先看下tss_struct源码,配了相应注释。

      // 摘自linux-4.9.229/arch/x86/include/asm/processor.h
      struct tss_struct {
      	/*
      	 * The hardware state:
      	 */
      	struct x86_hw_tss	x86_tss;
      
      	/*
      	 * The extra 1 is there because the CPU will access an
      	 * additional byte beyond the end of the IO permission
      	 * bitmap. The extra byte must be all 1 bits, and must
      	 * be within the limit.
      	 */
      	unsigned long		io_bitmap[IO_BITMAP_LONGS + 1];
      
      #ifdef CONFIG_X86_32
      	/*
      	 * Space for the temporary SYSENTER stack.
      	 */
      	unsigned long		SYSENTER_stack_canary;
      	unsigned long		SYSENTER_stack[64];
      #endif
      
      } ____cacheline_aligned;
      

      再查看其中的x86_hw_tss - 硬件状态结构,sp0表示Ring0状态下的栈顶指针,即内核栈栈顶指针。因此可以通过tr寄存器找到对应的tss结构体x86_tss,x86_tss中的sp0的值即为内核栈栈顶指针。

      // 摘自linux-4.9.229/arch/x86/include/asm/processor.h
      /* This is the TSS defined by the hardware. */
      struct x86_hw_tss {
      	unsigned short		back_link, __blh;
      	unsigned long		sp0;
      	unsigned short		ss0, __ss0h;
      	unsigned long		sp1;
      
      	/*
      	 * We don't use ring 1, so ss1 is a convenient scratch space in
      	 * the same cacheline as sp0.  We use ss1 to cache the value in
      	 * MSR_IA32_SYSENTER_CS.  When we context switch
      	 * MSR_IA32_SYSENTER_CS, we first check if the new value being
      	 * written matches ss1, and, if it's not, then we wrmsr the new
      	 * value and update ss1.
      	 *
      	 * The only reason we context switch MSR_IA32_SYSENTER_CS is
      	 * that we set it to zero in vm86 tasks to avoid corrupting the
      	 * stack if we were to go through the sysenter path from vm86
      	 * mode.
      	 */
      	unsigned short		ss1;	/* MSR_IA32_SYSENTER_CS */
      
      	unsigned short		__ss1h;
      	unsigned long		sp2;
      	unsigned short		ss2, __ss2h;
      	unsigned long		__cr3;
      	unsigned long		ip;
      	unsigned long		flags;
      	unsigned long		ax;
      	unsigned long		cx;
      	unsigned long		dx;
      	unsigned long		bx;
      	unsigned long		sp;
      	unsigned long		bp;
      	unsigned long		si;
      	unsigned long		di;
      	unsigned short		es, __esh;
      	unsigned short		cs, __csh;
      	unsigned short		ss, __ssh;
      	unsigned short		ds, __dsh;
      	unsigned short		fs, __fsh;
      	unsigned short		gs, __gsh;
      	unsigned short		ldt, __ldth;
      	unsigned short		trace;
      	unsigned short		io_bitmap_base;
      
      } __attribute__((packed));
      
      
    3. 目前为止我们已经找到了内核栈的栈基址和栈顶指针。因此可以将当前环境的cs, eip, eflags, ss, esp寄存器的值压入栈中。

    4. 将先前由中断向量检索得到的中断处理程序的 cs,ip 的值装入相应的寄存器,开始执行中断处理程序,这时已转到内核态。

    结语

    本文介绍了CPU特权级、用户态、内核态的相关概念,简要概括了由用户态进入内核态的三种方式:系统调用,异常,中断,事实上这三种方式在处理过程上是一致的,读者若想要了解更多内容请自行查阅资料。最后从源码的层面上讲解了从用户态切换到内核态的几个关键点——找到内核栈基址和内核栈栈顶指针。

    这里附上几个链接以供读者参考理解:
    为何要区分用户态和内核态
    用户态到内核态切换之奥秘解析
    用户态和内核态的理解和区别

    最后如本篇本章有错误或叙述不当地方,还请不吝赐教。

    展开全文
  • Linux 用户态和内核态由于 CPU 权限的限制,通信并不像想象中的使用进程间通信方式那么简单,今天这篇文章就来看看 Linux 用户态和内核态究竟有哪些通信方式。 我们平常在写代码时,一般是在用户空间,通过系统调用...
  • 用户态和内核态区别

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

    操作系统用户态和内核态之间的切换过程

    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信息装入相应的寄存器,开始执行中断处理程序,这时就转到了内核态的程序执行了。

    举个例子:

     

    下面的图中执行了连续的两条指令: mov eax, 0x4

     

                                                                      int 0x80

     

    可以看到,指令mov eax, 0x4对应的cs为0x7,eip为0x308a,ss为0xf,esp为0x80320

     

    这表明此条指令的特权级是3级,也就是说该指令是工作在用户态下的。

     

    int 0x80即所谓的系统调用执行的软中断,此条指令执行完之后,cs变换成了0x8,eip为0x1400,ss变成了0x10, esp 变成了0x1ffffec。这时系统已经转入了内核态执行,而且栈也变为了内核栈。

     

    内核态程序执行完毕时如果要从内核态返回用户态,可以通过执行指令iret来完成,指令iret会将先前压栈的进入内核态前的cs,eip,eflags,ss,esp信息从栈里弹出,加载到各个对应的寄存器中,重新开始执行用户态的程序,这个过程不再详述。

    展开全文
  • 文章来源于 拉钩教育 重学操作系统 林䭽 用户态和内核态用户态线程和内核态线程有什么区别? 什么是用户态和内核态 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 性能瓶颈、思考数据库连接池的配置等,要想完美地解决问题,就必须掌握这些模型,了解问题的本质上才能更好地思考问题衍生出来的问题。

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

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

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

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

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

    千次阅读 2019-05-14 13:59:52
    (1)用户态和内核态的概念? —>内核态: CPU可以访问内存所有数据, 包括外围设备, 例如硬盘, 网卡. CPU也可以将自己从一个程序切换到另一个程序 —>用户态: 只能受限的访问内存, 且不允许访问外围设备. 占用CPU...
  • 当一个任务(进程)执行系统调用而执行内核代码时,称进程处于内核内核态,此时处理器处于特权级最高的(0级)内核代码中执行,当进程处于内核态时,执行的内核代码会使用当前进程的内核栈,每个进程都有自己的内核栈...
  • 这节课给你带来了一道非常经典的面试题目:用户态线程和内核态线程有什么区别? 这是一个组合型的问题,由很多小问题组装而成,比如: 用户态和内核态是什么? 用户级线程和内核级线程是一个怎样的对应关系? ...
  • 用户态和内核态切换

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

    千次阅读 2021-03-19 10:48:38
    什么是用户态和内核态 从图上我们可以看出来通过系统调用将Linux整个体系分为用户态和内核态(或者说内核空间和用户空间)。 那内核态到底是什么呢?...为什么要区分内核态和用户态 往往我们的系统的资源是
  • 用户态和内核态的区别

    千次阅读 2021-02-16 20:14:22
    一、操作系统需要两种CPU状态 ... 举例:控制转移 算数运算 取数指令访管指令(使用户程序从用户态陷入内核态) 三、特权级别 特权环:R0、R1、R2R3 R0相当于内核态,R3相当于用户态; 不同级别能.
  • Java线程中的用户态和内核态

    千次阅读 2021-05-04 14:26:35
    内核态用户态是什么? 操作系统对程序的执行权限进行分级,分别为用户态和内核态用户态相比内核态有较低的执行权限,很多操作是不被操作系统允许的,简单来说就是用户态只能访问内存,防止程序错误影响到其他程序,而...
  • 1、用户态和内核态的区别? 明白这两个概念之前,我们得知道用户空间和内核空间。 用户空间:指的就是用户可以操作和访问的空间,这个空间通常存放我们用户自己写的数据等。 内核空间:是系统内核来操作的一块...
  • Linux下用户态和内核态内存共享的实现.pdf
  • 文章目录前言一、用户态和内核态的区分二、为什么要区分用户态和内核CPU指令集权限三、用户态和内核态切换切换开销用户态内核态切换的场景总结 前言 这篇文章记录笔者对于操作系统用户态和内核态的复习整理 一、...
  • 究竟什么是用户态,什么是内核态,这两个基本概念以前一直理解得不是很清楚,根本原因个人觉得是在于因为大部分时候我们在写程序时关注的重点着眼的角度放在了实现的功能代码的逻辑性上,先看一个例子: ...
  • 用户态和内核态之间的切换 切换方式 从用户态内核态切换可以通过三种方式,或者说会导致从用户态切换到内核态的操作: 系统调用,这个上面已经讲解过了,在我公众号之前的文章也有讲解过。其实系统调用本身就是...
  • 一、背景--线程状态切换的代价 ...用户态切换至内核态需要传递给许多变量、参数给内核,内核也需要保护好用户态在切换时的一些寄存器值、变量等,以便内核态调用结束后切换回用户态继续工作。 synch...
  • 经过编译,synchronized标注的函数会加一个读写锁,一般不推荐使用,因为加锁解锁设计到内核态用户态的转换,有时转化耗时比函数体执行时间还长,所以不推荐使用。 这个观点在学操作系统的时候作为常识被认知,那...
  • JVM线程用户态和内核态 一. 线程用户态和内核态概念 1.1 为什么会有用户态和内核态 由于需要限制不同的程序之间的访问能力, 防止他们获取别的程序的内存数据, 或者获取外围设备的数据, 并发送到网络, CPU划分出两个...
  • 什么是用户态和内核态

    千次阅读 2021-08-27 10:17:07
    用户态和内核态是操作系统的两种运行状态。 内核态:处于内核态的 CPU 可以访问任意的数据,包括外围设备,比如网卡、硬盘等,处于内核态的 CPU 可以从一个程序切换到另外一个程序,并且占用 CPU 不会发生抢占情况...
  • 要了解什么是用户态,什么是内核态,我们需要先了解什么是进程的用户空间内核空间:Linux虚拟内存的大小为2^32(在32位的x86机器上),内核将这4G字节的空间分为两部分。最高的1G字节(从虚地址0xC0000000到0...
  • 用户态和内核态 中断处理机制

    千次阅读 2021-01-15 22:57:54
    1.1 用户态和内核态 1.1.1 定义:什么是用户态和内核态? Kernel 运行在超级权限模式(Supervisor Mode)下,所以拥有很高的权限。按照权限管理的原则,多数应用程序应该运行在最小权限下。因此,很多操作系统,将...
  • Linux用户态和内核态交互的几种方式

    千次阅读 2019-01-22 18:45:49
    1/内核态->用户态  在kernel module中调用printk是最简单的传递信息到用户空间的方法。   2/用户态->内核态  在linux中,用户对设备的操作往往被抽象为对文件的操作。利用这一特性,可以通过...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 131,388
精华内容 52,555
关键字:

用户态和内核态

友情链接: MS02.rar