类似PHP、Nginx之类,需要频繁申请与释放内存的软件,一般都提供了用户态的内存管理。原因是,直接调用malloc/free会导致用户态到内核态的切换,较为耗时。那么,两者的区别到底是什么呢?

内核态与用户态的定义

CPU只会运行在以下两种状态:

  1. Kernel ModeIn Kernel mode, the executing code has complete and unrestricted access to the underlying hardware. It can execute any CPU instruction and reference any memory address. Kernel mode is generally reserved for the lowest-level, most trusted functions of the operating system. Crashes in kernel mode are catastrophic; they will halt the entire PC.
  2. User ModeIn User mode, the executing code has no ability to directly access hardware or reference memory. Code running in user mode must delegate to system APIs to access hardware or memory. Due to the protection afforded by this sort of isolation, crashes in user mode are always recoverable. Most of the code running on your computer will execute in user mode.
不同硬件的实现方式可能也不同,x86是通过0-3的4层protection rings硬件来划分的。据称Linux仅使用ring 0作为内核态,ring 3作为用户态,未涉及ring 1-2;而windows中部分drivers会使用ring 1-2。

何时会发生切换

Typically, there are 2 points of switching:

  1. When calling a System Call: after calling a System Call, the task voluntary calls pieces of code living in Kernel Mode
  2. When an IRQ (or exception) comes: after the IRQ an IRQ handler (or exception handler) is called, then control returns back to the task that was interrupted like nothing was happened.

IRQ全称为Interrupt Request,即是“中断请求”的意思,IRQ的作用就是在我们所用的电脑中,执行硬件中断请求的动作。

一般而言,系统调用是用户主动发起的,例如调用fork函数,会间接调用系统函数sys_fork,从而陷入内核态。而IRQ的发生也有用户“主动”和“被动”两种形式:例如用户调用malloc申请内存,可能会导致缺页异常,引发IRQ陷入内核态;或者我们需要读取硬盘中的一段数据时,当数据读取完毕,硬盘就通过IRQ来通知系统,相应的数据已经写到指定的内存中了。

切换成本

从用户态到内核态,本质上都是响应中断。因为系统调用实际上最终是中断机制实现的,而异常和中断的处理机制基本上也是一致的。其切换过程如下:

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

内核态到用户态需要将保存的进程信息予以恢复。

从上面的步骤可以看到,mode switch涉及大量数据的复制,还需要硬件配合,故耗时较大。而在不发生mode switch时,cpu只需顺序执行指令即可。所以应该尽量减少mode switch!

参考资料

http://blog.codinghorror.com/understanding-user-and-kernel-mode/

http://www.linfo.org/kernel_mode.html

http://www.tldp.org/HOWTO/KernelAnalysis-HOWTO-3.html

http://jakielong.iteye.com/blog/771663

http://os.ibds.kit.edu/downloads/publ_1995_liedtke_ukernel-construction.pdf

http://os.inf.tu-dresden.de/pubs/sosp97/

Leave a Reply