用户态与内核态的区别与理解

用户态与内核态的区别与理解

先给大家看看Linux进程的地址空间,如下:
用户态与内核态的区别与理解_第1张图片

对于Linux内核态的地址空间,3G-4G是大家共享的。这里存放的是整个内核的代码和所有的内核模块以及内核所维护的数据。

1、为什么需要区分内核空间和用户空间
在CPU的左右指令中,有些指令是非常危险的,如果错用,将导致系统崩溃,比如清内存、设置时钟等,如果允许所有的程序都可以使用这些指令,那么系统崩溃的概率将大大增加。所以,CPU将指令分为特权指令和非特权指令,对于那些危险的指令,只允许操作系统及其相关模块使用,普通应用程序只能使用那些不会造成灾难的指令。

2、内核态与用户态的概念
内核态:系统中既有操作系统的程序,也有普通用户的程序,为了安全和稳定性操作系统的程序不能随便访问。从本质上看是一种软件,控制计算机的硬件资源,并提供上层应用程序运行的环境。
用户态:不能直接使用系统资源,也不能改变CPU的工作状态,并且只能访问这个用户程序自己的存储空间。应用程序的执行必须依托于内核提供的资源,包括CPU资源、存储资源、I/O资源等。

3、特权级的概念
Linux使用了Ring3级别运行用户态,Ring0标识内核态。Ring0作为内核态,没有使用Ring1和Ring2。Ring3状态不能访问Ring0 的地址空间,包括代码和数据。0-3级别中,0级特权级最高,3级特权级最低。对于任何操作系统来说,创建一个进程是核心功能。创建进程要做很多工作,会消耗很多物理资源,比如分配物理内存、父子进程拷贝信息、拷贝设置页目录页等,这些都是由特定的进程去做,所有就有了上述的特权级别的概念。

4、用户态和内核态的切换
运行于用户态的进程可以执行的操作和访问的资源都会受到极大的限制,而运行在内核态的进程则可以执行任何操作并且在资源的使用上没有限制。当在系统中执行一个程序时,大部分时间是运行在用户态下的,在其需要操作系统帮助完成一些用户态自己没有特权和能力完成的操作时就会切换到内核态。以下是用户态转换成内核态的几种方式:

  • 系统调用
    这是用户进程主动要求切换到内核态的一种方式,用户进程通过系统调用申请操作系统提供的服务程序完成工作。而系统调用的机制其核心还是使用了操作系统为用户特别开放的一个中断来实现。
  • 异常
    当CPU在执行运行在用户态下的程序时,发生了一些没有预知的异常,这时会触发由当前运行进程切换到处理此异常的内核相关进程中,也就是切换到了内核态,如缺页异常。
  • 外围设备的中断
    当外围设备完成用户请求的操作之后,会向CPU发出相应的中断信号,这时CPU会暂停执行下一条将要执行的指令转而去执行中断信号的处理程序,如果先执行的指令是用户态下的程序,那么这个转换的过程自然也就发生了有用户态到内核态的切换。

以上三种方式是系统在运行时由用户态切换到内核态最主要的方式,其中系统调用可以认为是用户进程主动发起的,异常和外围设备中断则是被动的。
5、具体的切换操作
从触发方式上看,可以认为存在前述3种不同的类型,但是从最终实际完成由用户态到内核态的切换操作上来说,设计的关键步骤是完全一致的,没有任何区别,都相当于执行了一个中断响应的过程,因为系统调用实际上最终是中断机制实现的,而异常和中断的处理机制基本上也是一致的。用户态切换到内核态的步骤主要包括:

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

6、总结
现代的操作系统大都通过内核空间和用户空间的设计来保护操作系统自身的安全性和稳定性,本文只是从宏观的角度去理解Linux用户态和内核态的设计,并没有去深究他们的具体实现方式。因为用户态和内核态之间的切换会消耗大量资源,所有其实现必须考虑的一点就是性能问题。奈何本人才疏学浅,在此处就先不加以赘述,以后肯定会再做详细讲解!

你可能感兴趣的:(笔记,Linux,操作系统,内核,linux)