作为中央核心处理器的CPU,除了生产过程的不断创新和进步外,还需要平衡数据处理和响应速度。有一点微机原理基础的人都知道,IntelX86系统的CPU提供了四种权限模式ring0~ring3,其中ring0的权限为***,ring3的权限为***。做这样区分的主要目的是为了保护资源,一般来说,要保护的资源无非就是“内存、I/O端口、执行特殊机器指令的能力”。在任何时刻,x86CPU都在某种特权模式下运行。同样,ARM系统的CPU有七种运行模式,分别是:用户模式(usr)、快速中断模式(fiq)、中断模式(irq)、管理模式(svc)、系统模式(sys)、数据访问终止模式(abt)和未定义指令终止模式(und)。除用户模式外,其余6种工作模式均为特权模式,而在特权模式下,除系统模式外,其余5种模式也称为异常模式。那么底层硬件CPU的这个特性和我们要讨论的用户态和内核态有什么关系呢?让我们追根溯源,纠正我们对操作系统的认识。每个讲授操作系统课程的老师都会告诉大家:所谓操作系统就是统一管理硬件资源,为用户提供业务接口的软件系统。通俗地说,【操作系统就是要能够管理你的CPU和内存,驱动你的硬盘,管理你的网卡和显示器,然后在你点击鼠标和敲击键盘时做出正确的反应。]很简单。那么问题来了,以CPU为例,如果你是操作系统设计者,你会如何处理不同CPU架构(如Intel、ARM,或者AMD、MIPS等)的差异?当然,这个问题不适合普通人。如果能hold住,CU论坛开发都江堰操作系统的前辈确实值得我们敬佩和敬仰。继续我们的话题,也就是说,不同的操作系统在处理CPU架构的差异上是不一样的。有的操作系??统提供了用户态和内核态的机制(比如linux),而有的操作系??统呢,没有用户态和内核态的区分(比如vxWorks)。后者不在我们的讨论范围之内。有兴趣的童鞋可以自行谷歌。以Linux系统和Intelx86CPU为例,Linux使用ring0模式运行内核态代码,ring3运行用户态代码,ring1和ring2不使用。32是操作系统的可寻址范围是0~4GB,所以Linux系统将其分为用户空间和内核空间两部分:用户空间占用低3GB空间,范围为虚拟地址的0x00000000到0xBFFFFFFFF,以及内核空间占用高1GB的空间是保留的,虚拟地址范围是0xC0000000到0xFFFFFFFF。内核空间存放了整个内核代码和所有内核模块,以及内核维护的数据。当用户运行程序时,程序创建的进程最初运行在用户空间。当它需要执行网络发送数据等动作时,必须通过调用write、send等系统函数来完成。这些系统调用会去调用内核中的代码来完成用户的请求操作。这时CPU必须从ring3切换到ring0,然后进入内核地址空间执行这些代码,完成运算。完成后切换回ring3,回到用户态。因此,我们可以看到提供了用户态和内核态操作系统,用户态程序不能随意操作内核地址空间中的数据,具有一定的安全保护作用;同时,它的实时性稍差。牺牲了。也就是说,只要内核代码没有问题,用户空间程序的错误和bug一般不会导致系统崩溃,从而提高了系统的健壮性。从这一点来看,内核确实更“拉”一些,Linux也提供了一些用户空间和内核空间的通信机制,让我们可以开发出更高效的程序。但是我们一定要记住,内核中的一个小错误就会导致整个系统崩溃,所以我们在开发内核程序的时候一定要非常小心。
