目录

一、用户态与内核态的概念

二、为什么要有用户态和内核态

三、用户态与内核态的切换


在Linux的学习中经常会遇到用户态和内核态这两个术语,今天我们就来好好了解一下: 

一、用户态与内核态的概念

        先看一下Linux整体架构图:

        

        从图上我们可以看出来通过 系统调用 将Linux整个体系分为用户态和内核态(或者说内核空间和用户空间)

  • 用户态:提供应用程序运行的空间,为了使应用程序访问到内核管理的资源,例如CPU,内存,I/O等。
  • 内核态:本质是内核,一种特殊的软件程序用于控制计算机的硬件资源,例如协调CPU资源,分配内存资源,并且提供稳定的环境供应用程序运行。

        用户态只能受限的访问内存, 且不允许访问外设(硬盘、网卡等);内核态CPU可以访问内存所有数据, 包括外设,且可以将自己从一个程序切换到另一个程序。

  • 系统调用:操作系统对外会表现为一个整体,但是会暴露自己的部分接口来供上层开发使用,这部分由操作系统提供的接口,叫做系统调用。
  • 库函数:库函数实际上就是对系统调用接口的封装,提供简单的基本接口给用户
  • Shell:命令行,为了方便用户和系统交互。

 

二、为什么要有用户态和内核态

        由于需要限制不同的程序之间的访问能力, 防止他们获取别的程序的内存数据, 或者获取外设的数据并发送到网络,操作系统划分出两个权限等级: 用户态 和 内核态。

        简单来说,就是:对不同的操作给予不同的“权限”

 

三、用户态与内核态的切换

        用户程序跑在用户态下,但是如果需要执行一些操作例如申请内存,网络读写时,自己的权限不够,就需要转换到内核态去让内核的code帮忙干一些事情,这样就存在用户态和内核态切换的过程,例如:C库接口malloc申请动态内存,malloc的实现内部可能会调用 系统调用brk()来分配内存。

注意:

        上述例子提到的malloc的实现内部为什么是可能会进行系统调用而不是一定会进行系统调用呢?

        malloc是用于用户空间堆扩展的函数接口。该函数是C库,属于封装了相关系统调用(brk())的glibc库函数,而不是系统调用(系统可没有sys_malloc()),如果谈及malloc函数涉及的系统内核的那些操作,那么总体可以分为用户空间层面和内核空间层面来讨论:

  • 用户层面:每当进程调用malloc,首先会在该堆缓冲区寻找足够大小的内存块分配给进程(选择缓冲区中的那个块就有首次命中和最佳命中两种算法)。如果free_chunk_list已无法满足需求的chunk时,那么malloc会通过调用系统调用brk()将进程空间的堆进行扩展,在新扩展的堆空间上建立一个新的chunk并加入到空闲队列中,这个过程相当于进程想向系统批量申请一块内存
  • 内核层面:用户层面中如果malloc的空闲chunk列表无法满足用户的需求,那么就要通过sys_brk()进行堆的扩展,这时候才真正算得上进入内核空间。
  • 那么如何从用户态切换到内核态呢?有以下三种方式:
  1. 系统调用:是用户态进程主动要求切换到内核态的一种方式,用户态进程通过系统调用申请使用操作系统提供的服务程序完成工作。例如上面的例子、还比如fork()实际上就是执行了一个创建新进程的系统调用。(其实系统调用本身就是中断,是软件中断)
  2. 异常:如果当前进程运行在用户态,如果这个时候发生了异常事件,就会触发切换。例如:缺页异常。
  3. 外设中断:当外设完成用户的请求时,会向CPU发送中断信号,此时CPU会暂停执行下一条即将要执行的指令转而去执行与中断信号对应的处理程序,如果先前执行的指令是用户态下的程序,那么这个转换的过程自然也就发生了由用户态到内核态的切换。例:如硬盘读写操作完成后,系统会切换到硬盘读写的中断处理程序中执行后续操作。

 

  • 用户态切换到内核态的具体步骤:
  1. 从当前进程的描述符中提取其内核栈的ss0及esp0信息。
  2. 使用ss0和esp0指向的内核栈将当前进程的cs,eip,eflags,ss,esp信息保存起来,这个过程也完成了由用户栈到内核栈的切换过程,同时保存了被暂停执行的程序的下一条指令。
  3. 将先前由中断向量检索得到的中断处理程序的cs,eip信息装入相应的寄存器,开始执行中断处理程序,这时就转到了内核态的程序执行了。

用户态和内核态之间切换调度的成本很高,原因是什么?

答:Linux下每个进程的栈有两个,一个是用户态栈,一个是内核态栈。在从用户态栈进入内核的时候,进行执行栈的转换,需要保存用户态的寄存器,在内核态返回用户态的时候会恢复这些寄存器的内容,相对而言这是一个很大的开销且耗时。

 

  • 操作系统通过中断来从用户态切换到内核态内核态可以直接切换到用户态

 

 

Logo

更多推荐