本文以 32 位系统为例介绍内核空间(kernel space)和用户空间(user space)。html
对 32 位操做系统而言,它的寻址空间(虚拟地址空间,或叫线性地址空间)为 4G(2的32次方)。也就是说一个进程的最大地址空间为 4G。操做系统的核心是内核(kernel),它独立于普通的应用程序,能够访问受保护的内存空间,也有访问底层硬件设备的全部权限。为了保证内核的安全,如今的操做系统通常都强制用户进程不能直接操做内核。具体的实现方式基本都是由操做系统将虚拟地址空间划分为两部分,一部分为内核空间,另外一部分为用户空间。针对 Linux 操做系统而言,最高的 1G 字节(从虚拟地址 0xC0000000 到 0xFFFFFFFF)由内核使用,称为内核空间。而较低的 3G 字节(从虚拟地址 0x00000000 到 0xBFFFFFFF)由各个进程使用,称为用户空间。
对上面这段内容咱们能够这样理解:
每一个进程的 4G 地址空间中,最高 1G 都是同样的,即内核空间。只有剩余的 3G 才归进程本身使用。
换句话说就是, 最高 1G 的内核空间是被全部进程共享的!
下图描述了每一个进程 4G 地址空间的分配状况(此图来自互联网):linux
在 CPU 的全部指令中,有些指令是很是危险的,若是错用,将致使系统崩溃,好比清内存、设置时钟等。若是容许全部的程序均可以使用这些指令,那么系统崩溃的几率将大大增长。
因此,CPU 将指令分为特权指令和非特权指令,对于那些危险的指令,只容许操做系统及其相关模块使用,普通应用程序只能使用那些不会形成灾难的指令。好比 Intel 的 CPU 将特权等级分为 4 个级别:Ring0~Ring3。
其实 Linux 系统只使用了 Ring0 和 Ring3 两个运行级别(Windows 系统也是同样的)。当进程运行在 Ring3 级别时被称为运行在用户态,而运行在 Ring0 级别时被称为运行在内核态。安全
内核态与用户态网络
好了咱们如今须要再解释一下什么是内核态、用户态:
当进程运行在内核空间时就处于内核态,而进程运行在用户空间时则处于用户态。
在内核态下,进程运行在内核地址空间中,此时 CPU 能够执行任何指令。运行的代码也不受任何的限制,能够自由地访问任何有效地址,也能够直接进行端口的访问。
在用户态下,进程运行在用户地址空间中,被执行的代码要受到 CPU 的诸多检查,它们只能访问映射其地址空间的页表项中规定的在用户态下可访问页面的虚拟地址,且只能对任务状态段(TSS)中 I/O 许可位图(I/O Permission Bitmap)中规定的可访问端口进行直接访问。 spa
对于之前的 DOS 操做系统来讲,是没有内核空间、用户空间以及内核态、用户态这些概念的。能够认为全部的代码都是运行在内核态的,于是用户编写的应用程序代码能够很容易的让操做系统崩溃掉。
对于 Linux 来讲,经过区份内核空间和用户空间的设计,隔离了操做系统代码(操做系统的代码要比应用程序的代码健壮不少)与应用程序代码。即使是单个应用程序出现错误也不会影响到操做系统的稳定性,这样其它的程序还能够正常的运行(Linux 但是个多任务系统啊!)。操作系统
因此,区份内核空间和用户空间本质上是要提升操做系统的稳定性及可用性。.net
其实全部的系统资源管理都是在内核空间中完成的。好比读写磁盘文件,分配回收内存,从网络接口读写数据等等。咱们的应用程序是没法直接进行这样的操做的。可是咱们能够经过内核提供的接口来完成这样的任务。
好比应用程序要读取磁盘上的一个文件,它能够向内核发起一个 "系统调用" 告诉内核:"我要读取磁盘上的某某文件"。其实就是经过一个特殊的指令让进程从用户态进入到内核态(到了内核空间),在内核空间中,CPU 能够执行任何的指令,固然也包括从磁盘上读取数据。具体过程是先把数据读取到内核空间中,而后再把数据拷贝到用户空间并从内核态切换到用户态。此时应用程序已经从系统调用中返回而且拿到了想要的数据,能够开开心心的往下执行了。
简单说就是应用程序把高科技的事情(从磁盘读取文件)外包给了系统内核,系统内核作这些事情既专业又高效。设计
对于一个进程来说,从用户空间进入内核空间并最终返回到用户空间,这个过程是十分复杂的。举个例子,好比咱们常常接触的概念 "堆栈",其实进程在内核态和用户态各有一个堆栈。运行在用户空间时进程使用的是用户空间中的堆栈,而运行在内核空间时,进程使用的是内核空间中的堆栈。因此说,Linux 中每一个进程有两个栈,分别用于用户态和内核态。htm
下图简明的描述了用户态与内核态之间的转换:blog
既然用户态的进程必须切换成内核态才能使用系统的资源,那么咱们接下来就看看进程一共有多少种方式能够从用户态进入到内核态。归纳的说,有三种方式:系统调用、软中断和硬件中断。这三种方式每一种都涉及到大量的操做系统知识,因此这里不作展开。
接下来咱们从内核空间和用户空间的角度看一看整个 Linux 系统的结构。它大致能够分为三个部分,从下往上依次为:硬件 -> 内核空间 -> 用户空间。以下图所示(此图来自互联网):
在硬件之上,内核空间中的代码控制了硬件资源的使用权,用户空间中的代码只有经过内核暴露的系统调用接口(System Call Interface)才能使用到系统中的硬件资源。其实,不光是 Linux,Windows 操做系统的设计也是大同小异。
实际上咱们能够将每一个处理器在任何指定时间点上的活动归纳为下列三者之一:
以上三点几乎包括全部的状况,好比当 CPU 空闲时,内核就运行一个空进程,处于进程上下文,但运行在内核空间。
说明:Linux 系统的中断服务程序不在进程的上下文中执行,它们在一个与全部进程都无关的、专门的中断上下文中执行。之因此存在一个专门的执行环境,就是为了保证中断服务程序可以在第一时间响应和处理中断请求,而后快速地退出。
现代的操做系统大都经过内核空间和用户空间的设计来保护操做系统自身的安全性和稳定性。因此在咱们阅读有关操做系统的资料时常常遇到内核空间、用户空间和内核态、用户态等概念,但愿本文可以帮助您理解这些基本的概念。
参考: