开始学习
< 返回

Linux 内核空间和用户空间

本文以 32 位系统为例介绍 Linux 系统的内核空间(kernel space)和用户空间(user space)。

内核空间 vs 用户空间

对 32 位操作系统而言,它的寻址空间(虚拟地址空间)为 2 的 32 次方,也就是 4G。

Linux 系统的核心是内核(kernel),它独立于普通的应用程序,拥有访问受保护的内存空间和底层硬件设备的所有权限。为了保证内核的安全,现代操作系统一般都强制用户进程不能直接操作内核。具体的实现方式基本都是由操作系统将虚拟地址空间划分为两部分,一部分为内核空间,另一部分为用户空间。

针对 Linux 操作系统而言,最高的 1G 字节(从虚拟地址 0xC0000000 到 0xFFFFFFFF)由内核使用,称为内核空间。而较低的 3G 字节(从虚拟地址 0x00000000 到 0xBFFFFFFF)由各个进程使用,称为用户空间。

每个进程 4G 地址空间的分布情况如下:

实际上,程序员只能使用虚拟地址。系统中每个进程有各自的私有用户空间(0~3G),这个空间对系统中的其他进程是不可见的,而内核空间则是各个进程共享的。

为何区分

在 CPU 的所有指令中,有些指令是非常危险的,如果错用将导致系统崩溃,比如清内存、设置时钟等。如果允许所有的程序都可以使用这些指令,那么系统崩溃的概率将大大增加。因此,CPU 将指令分为特权指令和非特权指令,对于那些危险的指令,只允许操作系统及其相关模块使用,普通应用程序只能使用那些不会造成灾难的指令。比如 Intel 的 CPU 将特权等级分为 4 个级别:Ring0~Ring3。

其实 Linux 系统只使用了 Ring0 和 Ring3 两个运行级别(Windows 系统也是一样的)。当进程运行在 Ring3 级别时被称为运行在用户态,而运行在 Ring0 级别时被称为运行在内核态。当进程运行在内核空间时就处于内核态,而进程运行在用户空间时则处于用户态。

  • 在内核态下,进程运行在内核地址空间中,此时 CPU 可以执行任何指令。运行的代码也不受任何的限制,可以自由地访问任何有效地址,也可以直接进行端口的访问。
  • 在用户态下,进程运行在用户地址空间中,被执行的代码要受到 CPU 的诸多检查,它们只能访问映射其地址空间的页表项中规定的在用户态下可访问页面的虚拟地址,且只能对任务状态段(TSS)中 I/O 许可位图(I/O Permission Bitmap)中规定的可访问端口进行直接访问。

对于以前的 DOS 操作系统来说,是没有内核空间、用户空间以及内核态、用户态这些概念的。可以认为所有的代码都是运行在内核态的,因而用户编写的应用程序代码可以很容易的让操作系统崩溃掉。

Linux 通过区分内核空间和用户空间的设计,隔离了操作系统代码(操作系统的代码要比应用程序的代码健壮很多)与应用程序代码。即便是单个应用程序出现错误也不会影响到操作系统的稳定性,这样其它的程序还可以正常的运行(Linux 可是个多任务系统)。

所以,区分内核空间和用户空间本质上是要提高操作系统的稳定性及可用性。

状态切换

在 Linux 系统中,所有的系统资源管理都是在内核空间中完成的。比如读写磁盘文件、分配回收内存、从网络接口读写数据等等。应用程序是无法直接进行这样的操作的。但是可以通过内核提供的接口来完成这样的任务。

比如应用程序要读取磁盘上的一个文件,它可以向内核发起一个 "系统调用" 告诉内核:"我要读取磁盘上的某某文件"。其实就是通过一个特殊的指令让进程从用户态进入到内核态,在内核空间中,CPU 可以执行任何的指令,当然也包括从磁盘上读取数据。具体过程是先把数据读取到内核空间中,然后再把数据拷贝到用户空间并从内核态切换到用户态。此时应用程序已经从系统调用中返回并且拿到了想要的数据,可以开开心心的往下执行了。

简单来说,就是应用程序把操作系统资源的工作(从磁盘读取文件)统一交给系统内核来执行,系统内核做这些事情既专业又高效。

对于一个进程来讲,从用户空间进入内核空间并最终返回到用户空间,这个过程是十分复杂的。Linux 中每个进程有两个堆栈,分别用于用户态和内核态,在用户空间时进程使用的是用户空间中的堆栈,而运行在内核空间时,进程使用的是内核空间中的堆栈。下图简单描述了用户态与内核态之间的转换。

概括的说,一个进程有三种方式可以从用户态进入到内核态:系统调用、软中断和硬件中断

从内核空间和用户空间的角度来看整个 Linux 系统的结构,大致可以分为三个部分,从下往上依次为:硬件 -> 内核空间 -> 用户空间。在硬件之上,内核控制了所有硬件资源的使用权,用户空间中的程序只有通过内核暴露的系统调用接口(System Interface)才能使用到系统中的硬件资源。

小结

现代的操作系统大都通过内核空间和用户空间的设计来保护操作系统自身的安全性和稳定性。

Was this article helpful?
0 out of 5 stars
5 Stars 0%
4 Stars 0%
3 Stars 0%
2 Stars 0%
1 Stars 0%
Please Share Your Feedback
How Can We Improve This Article?
文章目录