![](https://i-blog.csdnimg.cn/blog_migrate/f5e8e9c4fc76765fd150316a2f8442f5.jpeg)
我是荔园微风,作为一名在IT界整整25年的老兵,今天我们来重新审视一下Windows这个我们熟悉的不能再熟悉的系统。说Windows操作系统的运行环境和运行状态,首先要介绍一下Windows操作系统的体系结构,然后再要说到最重要的两个概念:核心态与用户态。
操作系统的体系结构就是操作系统的组成结构。操作系统的体系结构主要包括模块组合结构、层次结构和微内核结构。下面来具体看看这三种,但我们这里不介绍宏内核和纵向结构内核。
模块组合结构
模块组合结构是软件工程出现以前的早期操作系统以及目前一些小型操作系统的体系结构。操作系统是一个有多种功能的系统程序,可以看作一个整体模块,也可以看作若干个模块按一定的结构方式组成的。系统中的每一个模块都是根据要完成的功能来划分的,这些功能模块按照一定的结构方式组合起来,协同完成整个系统的功能。优点是结构紧密、接口简单直接、系统的效率相对较高。缺点是首先这种结构的模块之间可以随意转接,各模块相互牵连,不容易把握好模块的独立性,导致系统结构不清晰。其次这种结构的可扩展性较差。在更换一个模块或修改一个模块时,要先弄清模块间的接口,如果要按当初设计的模块接口来设计新的模块,而当初设计的模块接口很可能是随意约定的,那么要做这项工作就存在一定难度。最后这种结构系统的可适应性差。随着系统规模的不断增大,采用这种结构构造的系统的复杂性会迅速增长,所以它只适用于系统小、模块少、使用环境比较稳定的系统。
层次结构
要弥补模块组合结构中模块间调用存在的不足之处,就必须改善模块间毫无规则的相互调用、相互依赖的关系,尤其要清除模块间的循环调用。层次结构的设计就是从这一点出发,力求使模块之间调用的无序性变为有序,减少了模块调用的无规则性。按层次结构来设计操作系统,就是将操作系统的所有功能模块按功能的调用次序排列成若干层,使得功能模块之间只存在单向调用和单向依赖。优点是模块间的组织和依赖关系清晰明了,上层功能是建立在下层功能基础之上的,系统的可读性、可适应性以及可靠性都得到了增强。此外,对某一层进行修改或替换时,最多只影响到邻近的两层,便于修改和扩充。缺点是操作系统的各个功能模块应该放在哪一层,如何有效地进行分层是必须要考虑的问题。为了增强其适应性,必须把与机器特点紧密相关的软件(如中断处理、输入/输出管理等)放在最底层;其次,要将最常用的操作方式放在最内层,而把随着这些操作方式改变的部分放在外层。另外,当前操作系统的设计都是基于进程的概念,通常要将为进程提供服务的系统调用模块放在系统的内层。
微内核结构
随着网络技术的普遍应用和发展,很有必要为用户提供一个符合处理分布式信息的分布式系统环境。因此,操作系统可以采用微内核结构。微内核的主要思想是:在操作系统内核中只留下一些最基本的功能,而将其他服务尽可能地从内核中分离出去,用若干个运行在用户态下的进程(即服务器进程)来实现,形成所谓的“客户/服务器”模式,即C/S模式。普通用户进程(即客户进程)可通过内核向服务器进程发送请求,以取得操作系统的服务。从微内核结构的主要思想可以看出,它非常适用于分布式系统。优点是首先每个服务进程运行在独立的用户进程中,即便某个服务器失败或产生问题,也不会引起系统其他服务器和其他组成部分的崩溃,可靠性好;其次系统具有很好的灵活性,只要接口规范,操作系统可以方便地增删服务功能;再次便于维护,即修改服务器的代码不会影响系统其他部分;最后这种结构的操作系统适合分布式处理的计算环境。缺点是这种结构的操作系统效率不高,因为所有用户进程都要通过微内核相互通信,所以微内核本身就成了系统的“瓶颈”,尤其是通信频繁的系统。
Windows操作系统以微内核结构起家,融合了宏内核的优点,形成了混合内核的特点,所以Windows操作系统是混合内核。由于本文是说Windows操作系统,不是介绍Linux操作系统,我们这里也就不介绍宏内核了,大家可以到CSDN上搜索宏内核的文章看。我们这里也没有介绍云计算和虚拟化,所以纵向结构内核(外内核)也不介绍了,纵向结构内核可能会在未来几年在云计算上发挥重要作用,本质上来说,纵向结构内核不同于宏内核和微内核的地方就在于,应用程序可以直接访问纵向结构内核资源。
Windows操作系统可以运行在多种环境下,通常包括传统环境(Windows PC等常见环境)、网络环境(分布式操作系统等)、嵌入式环境(Windows手机操作系统、家用电器的操作系统等)。这些属于操作系统的硬件环境,此外还有人机接口和操作系统与其他软件的关系。为了避免Windows操作系统及其关键数据(如PCB等)受到用户程序有意或无意的破坏,通常将处理器的执行状态分为两种:核心态与用户态。
核心态。核心态又称管态、系统态,是操作系统管理程序执行时机器所处的状态。注意,是机器当时所处的状态,不是程序所处的状态,这点要注意。它具有较高的特权,能执行包括特权指令的一切指令,能访问所有寄存器和存储区。
用户态。用户态又称目态,是用户程序执行时机器所处的状态,注意,是机器当时所处的状态,不是程序所处的状态,这点要注意。是具有较低特权的执行状态,它只能执行规定的指令,只能访问指定的寄存器和存储区。
划分核心态与用户态之后,这两类状态的相关程序以及各自的存储空间被严格区分了,而且在CPU执行时有着完全不同的待遇。用户态程序不能直接调用核心态程序,而是通过执行访问核心态的命令,引起中断,由中断系统转入操作系统内的相应程序,例如,在系统调用时,将由用户态转换到核心态。
特权指令:只能由操作系统内核部分使用,不允许用户直接使用的指令,如I/O指令、设置中断屏蔽指令、清内存指令、存储保护指令和设置时钟指令。
Windows操作系统中一些与硬件关联较紧密的模块(如时钟管理、中断处理、设备驱动等)以及运行频率较高的程序(如进程管理、存储器管理、设备管理等)构成了Windows操作系统的内核。内核的指令操作工作在核心态,主要包括以下4个方面的内容。
1)时钟管理。时钟是计算机的各部件中最关键的设备,Windows操作系统通过时钟管理,向用户提供标准的系统时间。另外通过时钟中断的管理,可以实现进程的切换,如时间片轮转调度。
2)中断机制。键盘或鼠标的输入、进程的管理和调度、系统功能的调用、设备驱动、文件访问等,无不依赖于中断机制。中断机制中,只有一小部分属于内核,负责保护和恢复中断现场的信息,转移控制权到相关的处理程序。这样可以减少终端的处理时间,提高系统的并行处理能力。
3)原语。计算机进程的控制通常由原语完成。所谓原语,一般是指由若干条指令组成的程序段,用来实现某个特定功能,在执行过程中不可被中断。在Windows操作系统中,某些被进程调用的操作,如队列操作、对信号量的操作、检查启动外设操作等,一旦开始执行,就不能被中断,否则就会出现操作错误,造成系统混乱。所以,这些操作都要用原语来实现。原语是操作系统核心(不是由进程,而是由一组程序模块组成)的一个组成部分,并且常驻内存,通常在管态下执行。原语一旦开始执行,就要连续执行完,不允许中断。处于操作系统最底层,是最接近硬件的部分。这些程序的运行时间较短,调用频繁。原语是在操作系统中调用核心层子程序的指令。与一般广义指令的区别在于它是不可中断的,而且总是作为一个基本单位出现。它与一般过程的区别在于:它们是“原子操作(primitive or atomic action)”。所谓原子操作,是指一个操作中的所有动作要么全做,要么全不做。换言之,它是一个不可分割的基本单位,因此,在执行过程中不允许被中断。原子操作在管态下执行,常驻内存。原语的作用是为了实现进程的通信和控制,系统对进程的控制如不使用原语,就会造成其状态的不确定性,从而达不到进程控制的目的。
4)系统控制的数据结构及处理。Windows操作系统中需要一些用来登记状态信息的数据结构,如作业控制块、进程控制块、设备控制块、各类链表、消息队列、缓冲器、空闲登记区、内存分配表等。除此之外还应该定义对这些数据结构的一系列操作:进程管理、存储器管理、设备管理。
这里要补充说明一下Windows操作系统的中断与异常。中断与异常是一对类似但又有区别的概念。中断,也称外中断,是系统正常功能的一部分,例如,因进程调度使系统停止当前运行的进程转而执行其他进程,或者因缺少所需资源而中断当前操作等待资源到达,在系统处理完其他事情之后,会继续执行中断前的进程。异常,也称内中断,是由错误引起的,如文件损坏、进程越界等。通常异常会引起中断,而中断未必是由异常引起的。
最后说一下Windows操作系统的系统调用。
系统调用是Windows操作系统提供的用户接口之一,是由Windows操作系统实现的所有系统调用所构成的集合,即程序接口或应用编程接口(Application Programming Interface,API),是应用程序同系统之间的接口。
Windows操作系统的主要功能是为应用程序的运行创建良好的环境。为了达到这个目的,内核提供了一系列具备预定功能的内核函数,通过一组称为系统调用(System Call)的接口呈现给用户。系统调用把应用程序的请求传给内核,调用相应的内核函数完成所需的处理,并将处理结果返回给应用程序。如果没有系统调用和内核函数,用户将不能编写大型应用程序。Windows操作系统提供的系统调用通常包括进程控制、文件系统控制(文件读写操作和文件系统操作)、系统控制、内存管理、网络管理、socket控制、用户管理以及进程间通信(信号、消息、管道、信号量和共享内存)。
Windows操作系统执行系统调用的流程如下面两图所示。用户需要执行系统调用时,首先准备并传递系统调用所需的参数,通过陷入(trap)指令进入操作系统的系统内核,此时将从用户态进入内核态;之后执行相应的系统调用函数,使用特定的系统内核功能;最后将处理结果返回给用户进程,此时将从内核态返回用户态。
操作系统执行系统调用的流程画法一:
![](https://i-blog.csdnimg.cn/blog_migrate/ebd2eb371570e06e7bd571f7d322667b.png)
操作系统执行系统调用的流程画法二:
![](https://i-blog.csdnimg.cn/blog_migrate/42511ade6f47715f15e1662bee0e404a.png)
操作系统执行系统调用的流程画法三:
![](https://i-blog.csdnimg.cn/blog_migrate/2415591ee75d6c69b2698b98ddb53b30.png)
操作系统执行系统调用的流程画法四:
![](https://i-blog.csdnimg.cn/blog_migrate/03478626e837fb87425a3932354149f5.png)
操作系统执行系统调用的流程画法五:
![](https://i-blog.csdnimg.cn/blog_migrate/280ffa8a53b075753e6b8cd3a5ae07b0.png)
这种五种画法我认为都是很经典的,究竟哪一种更适合你理解,仁者见仁。大家可以选择一种画法去理解。我个人认为第三种画法画得最好。
作者简介:荔园微风,1981年生,高级工程师,浙大工学硕士,软件工程项目主管,做过程序员、软件设计师、系统架构师,早期的Windows程序员,Visual Studio忠实用户,C/C++使用者,是一位在计算机界学习、拼搏、奋斗了25年的老将,经历了UNIX时代、桌面WIN32时代、Web应用时代、云计算时代、手机安卓时代、大数据时代、ICT时代、AI深度学习时代、智能机器时代,我不知道未来还会有什么时代,只记得这一路走来,充满着艰辛与收获,愿同大家一起走下去,充满希望的走下去。