206 lines
51 KiB
TeX
206 lines
51 KiB
TeX
% !TEX root = main.tex
|
||
|
||
|
||
\section{概述}
|
||
系统软件\index{系统软件}是驱动下层计算资源有效运转、为上层应用提供共性支撑的软件,主要包括操作系统、编译系统、中间件和数据库管理系统。其中,操作系统\index{操作系统}负责管理计算系统软硬件资源、操纵程序运行,为应用软件提供公用支撑;编译系统(又称编译器)负责将源语言编写的源程序翻译为等价的可运行目标程序;中间件将系统软件的概念扩展到网络环境,为分布式应用软件部署、运行和管理提供支撑;数据库管理系统旨在统一管理和维护数据库中的数据,是组织、存储、存取、控制和维护数据的软件。
|
||
|
||
与面向特定领域、解决特定问题的应用软件不同,系统软件是运行于计算“系统”层面上的软件。此处的“系统”有两层含义:
|
||
|
||
\begin{itemize}
|
||
\item 系统软件将计算系统的概念从硬件扩展到了软件层面。通过将底层硬件资源进行适当地抽象和封装,系统软件为上层应用提供了一个软件平台\index{软件平台}(也可以称为“虚拟机”\index{虚拟机}),使得上层应用软件可以方便地使用各类资源,无需关注底层细节。这一平台承担了共性的资源管理功能,屏蔽了异构性和细节,使得计算系统易于使用、易于编程。系统软件作为平台化的基础设施,封装了许多共性问题的解决方案,以避免应用软件去“重复发明轮子”。
|
||
\item 系统软件是驱动计算系统有效运转的控制器/协调者。一方面系统软件与计算系统中各类硬件资源直接交互,管理、调度和使用这些资源,使之可以高效协同;另一方面系统软件也直接管控上层应用的运行,从而达到提高程序装载和调度的自动化程度、提高资源利用率等目标。例如,操作系统可以通过批处理、分时共享等方法来实现计算系统的任务切换,因此早期也被称为“监督程序”(Supervisory Program)或“控制程序/例程”(Control Program/Routine)\cite{bullynck2018operating}。
|
||
\end{itemize}
|
||
|
||
系统软件并不是与计算机一起诞生的,它的出现有内因和外因两个方面。早期的计算机(如ENIAC)编程采用接线和开关等手工操作方式,并没有系统软件的概念。即使存储程序计算机出现之后,除了汇编器等带有系统软件思想的工具外,操作系统等主流系统软件并未马上出现,应用软件仍是直接在裸机上运行。但是,人们很快认识到,将应用与硬件裸机直接绑定,无论是编程效率、应用管理/切换效率还是底层资源利用率都十分低下。特别是早期CPU速度和I/O速度之间的巨大差异,基于时分复用的“虚拟化”成为客观需求,推动了系统软件、尤其是操作系统的快速发展。系统软件出现的外因则是软件复杂性增长所导致的分工细化,特别是上个世纪50-60年代,面向底层硬件资源的系统程序设计(System Programming)和面向领域的应用程序设计(Application Programming)的分化,以及系统程序员和应用程序员的分工,直接推动了系统软件这一概念的广泛接受。
|
||
|
||
\section{操作系统}
|
||
从功能定位的角度而言,操作系统\index{操作系统}是负责管理硬件资源、控制程序运行、改善人机界面和为应用提供支持的系统软件,是计算机软件生态链的基础核心。在一个计算系统中,操作系统向下是最靠近硬件的一层软件,它通过调用硬件驱动程序、固件等方式实现对硬件的管理;向上屏蔽硬件细节,为应用软件提供功能更为完善、灵活可编程的“虚拟机”,实现对各类应用软件的运行管理。因此,操作系统兼具“承上启下”和“管家”两类作用。由于操作系统的特殊地位,其发展与上层应用需求和底层硬件形态的演化都有着密切联系。从最初与硬件和应用场景高度绑定,到之后逐渐独立于硬件,操作系统向上提供的服务越来越多、向下针对硬件的抽象程度越来越高,其内涵和外延不断拓宽,并在积累一段时间后产生质变,呈现出主机计算、个人计算、互联网和移动计算等明显阶段性特点(图\ref{fig:3-1})。
|
||
|
||
\begin{figure}[htbp]
|
||
\centering
|
||
\includegraphics[width=0.90\textwidth]{fig1-3/3-1.png}
|
||
\caption{操作系统发展历程
|
||
\label{fig:3-1}}
|
||
\end{figure}
|
||
|
||
\subsection{单道批处理操作系统}
|
||
早期的存储程序计算机并没有操作系统,需由用户或专门操作人员管理计算任务,包括装入打孔卡片或纸带、通过包含开关和指示灯的控制面板来了解状态、在出错时进行必要干预等。这一方式可以满足早期少量科学计算的需要。但是随着计算机应用从传统科学计算领域向国防、政府、商业等通用领域拓展,计算任务及相关的数据量迅速增长,手工管理成为了制约计算机利用效率的瓶颈问题。用软件代替操作人员实现计算任务自动管理(包括载入和执行),这是操作系统出现的动因之一,并直接催生了第一代的批处理操作系统\index{批处理操作系统}。由于其强调替代人进行监管,这一时期的操作系统多被冠以“控制程序/例程”(Control Program/Routine)、“管程”(Monitor)、“监督例程”(Supervisory Routine)等名称。典型实例是通用汽车与北美航空于1956年基于IBM 704所开发的GM-NAA IO系统\cite{patrick1987general},其核心的管程可以从磁带上顺序读入和自动批量执行应用程序。该系统通常被认为是第一个成熟的商用操作系统,在20世纪50年代末被移植到多个巨型机上。
|
||
|
||
操作系统出现的另一个背景是20世纪 50年代计算机技术的革新,特别是磁芯内存、磁带等大容量高速存储技术的应用,以及从早期打孔卡片发展而来的“文件”等概念的出现,使得专业化的大型软件成为可能,软件开发作为一个独立行业开始从硬件设计制造中分离出来。人们针对“如何提高软件开发的效率”这一问题进行初步探索,催生了Fortran等高级语言,也在这一过程中积累了大量工具、编译器、可重用例程和库等。由于软件开发与运行密切相关,因此在这一时期,许多操作系统与编程系统并未严格区分,典型实例包括麻省理工学院的CSSR(Comprehensive System of Service Routines)\cite{Bennington:1956:LLU:1455410.1455416}、ERA 1103(UNIVAC 1103A)计算机所配备的“集成计算系统”\cite{Bauer:1956:ICS:320831.320836}等。这类系统通常具备运行时批处理功能,但更强调对开发的支持,其核心是一系列可重用库和辅助工具(Utility Tool)。这也是今天操作系统“沉淀共性解决方案”能力的起源。
|
||
|
||
虽然第一代操作系统以批处理模式为主,但由于指挥控制、工业自动化等领域对计算机的迫切需求,早期人们也在实时(或者至少能够在线处理的)操作系统方面开展了实践。典型案例是上个世纪50年代美国军方半自动地面防空系统(Semi Automatic Ground Environment,SAGE)项目\footnote{https://en.wikipedia.org/wiki/Semi-Automatic\_Ground\_Environment},这一系统通过多个主机实现了雷达数据的实时汇聚、处理和态势生成。由于其操作系统能够实现计算和I/O操作过程的交叠、完成数据的在线处理,在部份文献中被认为是首个实时操作系统\index{实时操作系统}。
|
||
|
||
\subsection{多道和分时主机操作系统}
|
||
在大型主机时代,操作系统的发展主要围绕着提高计算资源的利用率和提高操作系统的抽象能力两条主线展开:
|
||
|
||
\begin{enumerate}[(1)]
|
||
\item 提高计算资源的利用率
|
||
|
||
早期的操作系统采用单道批处理作业模型,此处的“单道”是指能够批量运行任务、减少了手工切换开销,但是在执行过程中只有单个程序在排他运行。由于CPU时间被大量浪费在等待I/O数据的过程中,资源利用率仍然相当低。1956年,UNIVAC 1103A计算机引入了硬件中断(Interrupt)\index{中断}的概念,为多个应用分时运行奠定了基础。此后,软件技术(如任务调度技术)和硬件技术(如内存保护机制)的协同发展,使得多道批处理、分时系统等支持多道程序设计(Multiprogramming)\index{多道程序设计}的操作系统开始出现。
|
||
|
||
\begin{itemize}
|
||
\item 多道批处理\index{多道批处理}是对单道批处理的扩展,允许单一计算机同时载入多个作业,使之可以以恰当的调度策略交替占用CPU,从而提高资源利用率,其典型案例是20世纪60年代由荷兰计算机科学家Dijkstra所领导研发、基于层次化架构的THE操作系统\cite{Dijkstra:1968:SLS:363095.363143}。
|
||
\item 分时系统\index{分时系统}的思想几乎与操作系统同时出现,其目标是“通过分时共享,使得一台大的计算机能够像多台小型计算机一样使用” \cite{Bauer:1958:CDP:1458043.1458055}。从1961年的首个MIT CTSS分时操作系统\cite{Lee:1992:TMI:612400.612428}开始,此类系统均通过CPU时间片的划分来支持多个终端用户。
|
||
\end{itemize}
|
||
|
||
在CTSS的基础上,1965年麻省理工学院、贝尔实验室和通用电气公司提出MULTICS(MULTiplexed Information and Computing Service)多用户多任务操作系统研制计划\cite{Corbato:1965:IOM:1463891.1463912}。该计划由于目标过于宏大而导致研制历经坎坷,但所提出的动态链接、分层文件系统\index{文件系统}等诸多思想对随后的操作系统产生了巨大的影响,并直接促成了1969年UNIX\index{UNIX}操作系统的诞生\cite{Bach:1986:DUO:8570}。UNIX是支持多种处理器架构的多用户多任务分时操作系统,最早运行于小型机PDP-11上,在其诞生后的50年中对操作系统的研究和实践产生了较大影响。20世纪80年代末IEEE和ISO组织基于UNIX发布的可移植操作系统接口(Portable Operating System Interface of UNIX,POSIX)\index{可移植操作系统接口}标准已成为操作系统领域的事实标准。
|
||
|
||
\item 提高操作系统的抽象能力
|
||
|
||
在这一阶段,一系列重要的、今天所熟知的操作系统抽象(及其实现机理)被确立。其中,20世纪50年代“文件”已经被用于描述存储于外部存储器(如磁鼓)中的数据单元,60年代初文件系统已经成为许多操作系统的基本组件,并在Unix操作系统中扩展为对所有I/O设备能力的抽象;内存分页(段)和虚拟内存于1959年在英国曼彻斯特大学Atlas计算机原型系统中首先实现,并很快出现在60年代的商用计算机中,成为对内存资源的基本使用方式;多道程序、特别是分时共享理念的发展,推动了进程和线程的概念被提出,二者至今仍是CPU资源调度和使用的基本单位。上述抽象奠定了现代操作系统内核设计与实现的基础,也逐渐在软件领域形成了对“操作系统应当如何抽象计算机硬件能力”这一问题的共识。
|
||
|
||
与操作抽象能力提升相关的一个里程碑事件是“兼容”概念的提出。早期操作系统往往绑定到特定机型甚至特定应用场景,许多操作系统是计算机最终用户所开发或定制的。进入20世纪60年代,集成电路的发明促使计算技术迅速向工业、商业、教育等各个领域渗透,与硬件和应用场景高度绑定的操作系统已经无法满足日益增长的需求。在这一背景下,IBM于1961年启动OS/360研制计划\cite{Mealy:1966:FSO:1663370.1663371},旨在为System/360系列计算机开发了统一的批处理操作系统,为应用软件提供标准化、与特定机型和应用场景解耦的运行环境。其后,1968年发布的CP-67操作系统和1972年发布VM/370操作系统扩展了分时共享的思想,首次提供了成熟的虚拟化\index{虚拟化}能力\cite{Creasy:1981:OVT:1664853.1664863},并率先使用了今天被广泛接受的“虚拟机监视器”(Hypervisor)一词。“兼容”概念自此开始深入人心:操作系统与硬件和应用场景解耦,使得上层应用在任何时候都看到是一个标准化的、具有通用图灵机\index{通用图灵机}能力的“虚拟机”,而不同型号的硬件也通过操作系统的抽象封装\index{抽象封装},以一致的方式向上层应用提供其能力。这一思路直接推动了整个计算机软硬件生态链的快速发展。
|
||
|
||
\end{enumerate}
|
||
|
||
\subsection{个人/嵌入式操作系统}
|
||
20世纪70年代集成电路技术的高速发展推动了微处理器的出现,“旧时王谢堂前燕”的计算技术开始“飞入寻常百姓家”,并直接推动了操作系统技术的发展。具体表现为:一方面,个人计算机迅速普及,产品和技术快速发展,使得能“兼容”多种软硬件的操作系统成为主流,而且用户的非专业化使得图形用户界面成为主流操作系统的内嵌能力;另一方面,由于工业控制、航空航天、武器装备等领域微处理器的应用,嵌入和实时操作系统作为操作系统的一个分支开始登上历史舞台。此外,这一时期的开源操作系统(如Linux)对本领域后续发展产生了深远影响。
|
||
|
||
\begin{enumerate}[(1)]
|
||
\item 个人计算机操作系统
|
||
|
||
70年代中期Intel发布8080 CPU以后,Digital Research发布了最早的微型计算机操作系统CP/M-80,它由基本输入输出系统(Basic Input/Output System,BIOS)、基本磁盘操作系统和控制台命令处理程序组成。其中,基本输入输出系统的引入,实现了操作系统其它模块与低层具体硬件的解耦,显著提高了操作系统的适用性和上层应用的可移植性。这种操作系统与具体硬件解耦的思想拓展了System/360大型机时代所提出的“兼容”概念,被后来的微软MS-DOS(Microsoft Disk Operating System)等操作系统所延续,直接为个人计算机软硬件生态链的快速发展奠定了基础。
|
||
|
||
在个人计算机时代,操作系统的另一个重要进展是图形用户界面的加入。早在1973年,Xerox即推出了支持可视化操作的Alto计算机,并于1981年发布了集成完整图形化桌面的操作系统Xerox 8010 Star;1984年Apple发布了具有图形用户界面的个人计算机Lisa;1985年微软公司发布了Windows系列操作系统。图形用户界面的发展极大地促进了个人计算机的普及:由于个人计算机面对的不是专业用户,易用性成为了操作系统的瓶颈问题,因此基于窗口和鼠标的直观操作取代了繁琐晦涩的命令行界面。在此基础上,浏览器、音/视频播放器等一些常用软件开始被打包内置到操作系统中,拓展了操作系统“沉淀共性解决方案”这一角色的内涵,也即不仅提供运行库供上层应用调用,也能直接支撑用户使用计算机完成常用功能。
|
||
|
||
此外,90年代初Linux\index{Linux}操作系统以开源软件形式出现,对操作系统技术、产品、产业乃至于相关法律政策、社会文化等都产生了重大影响。开源作为一种群智汇聚、群体协作的有效方式,一方面可以有效推动操作系统产品的发展,应对操作系统自身的复杂性;另一方面,一个操作系统能否被广泛接受也取决于其生态链的完善程度,而开源则为生态链构建提供了一种基于众包的新模式。
|
||
|
||
\item 嵌入和实时操作系统
|
||
|
||
20世纪70年代单片机出现是计算机发展史上的重要事件之一,它使得在各类设备中“嵌入”计算机成为可能,可被视为最早的“信息物理融合”(Cyber-Physical)尝试。80年代,强调轻量级的嵌入式操作系统\index{嵌入式操作系统}开始出现,此类操作系统在资源受限环境下运行,并且由于其与物理世界直接交互,往往同时需要提供对实时性(时间可预测性)的保证。首个商业嵌入式实时操作系统内核VTRX32于1981年发布,后续涌现出了vxWorks、uCOS、QNX等一系列被广泛应用的嵌入式实时操作系统产品。
|
||
|
||
\end{enumerate}
|
||
|
||
\subsection{智能终端操作系统}
|
||
进入21世纪,新型计算模式不断出现,计算技术表现出两极化的趋势:一方面以“云”为核心,强调通过资源集约化和按需服务方式,推动信息技术实现社会化和专业化;另一方面以“端”为核心,强调信息技术的普适化,使得计算服务如同水、电、空气一样随时随地可以获取而又不可见。需要指出的是,“云”和“端”二者并非割裂的,而是优势互补,正在通过“云+端”等形式共同推动着计算技术的新一轮革命。
|
||
|
||
当前,“云”上的系统软件形态主要以“平台即服务”基础设施等形式出现,它们运行于经典操作系统(如Linux)之上,可被视为中间件技术的发展(参见\ref{internet-middleware}节)。“端”操作系统的代表则是已经广泛商用的移动操作系统\index{移动操作系统},典型实例包括早期的Newton OS、WinCE到今天广泛使用的Google Android和Apple iOS。此类操作系统在架构上与个人计算机操作系统并无本质区别,但更强调对移动和手持环境的支持,包括移动网络接入、各类传感器支持、电池管理、触摸屏交互等。与个人计算时代类似,操作系统在移动计算软硬件生态链中同样具有核心基础地位,特别是操作系统内置应用商店的出现,在降低用户查找、获取和安装应用程序难度的同时,也形成了可持续的商业模型,极大推动了以操作系统为核心的软件生态链的成长。移动操作系统当前还表现出了与桌面系统一体化的发展趋势,通过统一桌面和移动操作系统及其生态,将有利于操作系统更好地发展与维护。例如,谷歌继移动操作系统Android和轻量级桌面操作系统ChromeOS之后,正在研制跨平台的Fuchsia操作系统。
|
||
|
||
近年来,以Android Things、Ubuntu Core、Mbed和华为“鸿蒙”等为代表的物联网操作系统\index{物联网操作系统}正在成为操作系统领域的新热点。此类操作系统在嵌入式操作系统基础上,一方面强调对“连接”、以及建立在连接基础上的分布计算甚至“云-端”融合的支持,从而有力支撑“万物互联”的目标;另一方面强调对异构物理网设备能力的统一抽象,从而屏蔽物联网设备的碎片化特征,为提升物联网的可管理性和可维护性、构建物联网良好生态环境奠定基础。
|
||
|
||
\section{编译系统}
|
||
编译系统\index{编译系统}是将源语言(例如高级程序设计语言)编写的代码翻译为等价的、高效的、能被计算机或虚拟机执行的目标代码(例如机器语言)的系统软件。编译系统的诞生早于操作系统,但如前节所述,由于软件开发与运行的密切相关性,在计算机发展早期,通常并不严格区分操作系统(Operating System)和编程系统(Programming System),仅仅是后者更强调其对开发的支持,内置了编译能力、开发辅助工具和可重用例程/库等。随着程序设计语言的变迁、特别是高级语言的出现,编译系统逐渐成为系统软件的一个主要分支,其内涵和外延随语言及计算机体系结构的发展而不断扩展(图\ref{fig:3-2})。
|
||
|
||
\begin{figure}[htbp]
|
||
\centering
|
||
\includegraphics[width=0.95\textwidth]{fig1-3/3-2.png}
|
||
\caption{编译系统发展历程
|
||
\label{fig:3-2}}
|
||
\end{figure}
|
||
|
||
\subsection{从汇编器到高级程序编译器}
|
||
|
||
作为机器体系结构抽象的符号化语言,汇编语言的目标是提高编程效率和质量。然而,计算机能读懂的只有机器指令,此时需要一个能够将汇编指令转换成机器指令的翻译程序。1947年伦敦大学伯贝克学院的Kathleen Booth为ARC2计算机开发了第一个汇编语言及其机器汇编器。之后不久,开始出现带有支持代码“库”的计算机,预先记录在打孔卡片和磁带上的支持代码库能够在装载器(Loader)的支持下与用户程序进行连接,从而支持输入输出等操作。这就是编译系统这种系统软件类型最早的雏形。
|
||
|
||
虽然汇编语言相对于机器语言提高了程序的可读性,但编写、阅读和理解汇编语言的难度依然较高。20世纪50年代初,Grace Hopper在UNIVAC I上首次使用了“编译器”(Compiler)一词。在她所实现的编译器中,磁带上的每段例程由一个数字代码标识,用户输入一组数字代码,来使得计算机依次加载这些例程。Grace Hopper工作证明了高级语言(数字代码)向机器语言(磁带上例程中所包含机器指令序列)映射的可行性。在此基础上,更为激进的“自动编程”(Automatic Programming)的概念\cite{hopper1953influence}被提出,希望能够采用接近于人类自然语言的语言编写程序,依据这些程序自动生成可执行的机器代码,从而显著提高程序开发效率和质量、便于程序的理解和维护。在这一思想的驱动下,上个世纪50年代出现了第一个高级程序设计语言——为IBM 704大型机设计的Fortran语言\cite{Backus:1978:HFI:960118.808380}。1957年发布的Fortran编译器是第一个功能比较完备的高级程序语言编译器。它也是第一个具备优化能力的编译器,引入了循环优化、寄存器分配等技术,使编译器翻译的机器代码有可能与当时人工编写的汇编程序性能相当。
|
||
|
||
\subsection{面向程序设计语言的编译系统}
|
||
在高级程序设计语言出现以后,程序设计方法学和程序设计语言飞速发展,诸如结构化程序设计\index{结构化程序设计}、面向对象程序设计\index{面向对象程序设计}、函数式程序设计\index{函数式程序设计}、逻辑程序设计\index{逻辑程序设计}等方法和语言百花齐放,直接推动了编译技术和编译系统的发展。
|
||
|
||
20世纪50年代末,COBOL(Common Business-Oriented Language)语言诞生\cite{Sammet:1978:EHC:960118.808378}。与Fortran主要面向科学和工程计算不同,COBOL是用于商务数据处理的语言,也是第一个跨平台的高级程序设计语言。1960年,由不同编译器编译的同一COBOL程序成功在UNIVAC II和RCA 501机上运行,表明了不同主机代码级兼容的可行性。70年代初,美国贝尔实验室以开发了B语言和B语言编译器,并用B语言编写了第一个UNIX操作系统内核。在B语言基础上,贝尔实验室经过进一步改进完善后发布了C语言及其编译器。
|
||
|
||
相对于Fortran和C等命令式高级语言,面向对象语言也在这一时期得到发展。20世纪60年代的SIMULA67语言\cite{Dahl:1968:FSL:800166.805258}引入了类和对象的概念,被认为是世界上第一个面向对象语言。70年代出现的Smalltalk语言支持类的动态创建和修改。受到C和SIMULA67语言的影响,贝尔实验室在八十年代开发了C++,随后开发了支持C++的Cfront编译器。20世纪90年代,随着C++等语言的流行,面向对象语言成为主流的编程语言,重要标志是GCC编译器(GNU Compiler Collection)走向成熟,以及Java面向对象语言和编译器的发布。这一时期互联网的发展也促进了编程语言及其编译/解释执行系统的发展,例如出现了面向互联网开发、在运行时检查类型甚至改变程序结构的动态语言(如PHP、Ruby等)。
|
||
|
||
60-70年代,编译系统的基础理论和相关技术也开始成熟。20世纪50年代,Noam Chomsky通过研究自然语言结构提出Chomsky文法类型,其中上下文无关文法成为现今几乎所有程序设计语言的语法\cite{chomsky1956three}。60年代至80年代,用于上下文无关文法识别的有效算法逐步发展为编译原理的标准部分,同时科学家们着眼研究编译器的自动构造,典型实例包括为UNIX操作系统研制的词法分析器生成工具Lex和语法分析器生成工具Yacc。编译系统中的代码优化研究也起步于这一阶段,包括与处理器体系结构无关的优化(如循环变换、常量传播、公共表达式删除)以及与处理器体系结构相关的优化(如寄存器分配、指令调度),后者与当时精简指令集、超标量、超长指令字等体系结构技术的发展密不可分。
|
||
|
||
\subsection{针对多核/众核架构优化的编译系统}
|
||
提高处理器性能是计算机领域长期追求的目标。随着处理器功耗、散热和设计复杂度等原因,在单核处理器上提高时钟频率的方法已无法继续提高处理器性能。因此,学术界和工业界开始改变策略,通过增加处理器核心数目来扩展性能。2001年,第一款商用非嵌入式多核处理器IBM POWER4发布,计算机体系结构发展进入多核时代。然而,增加处理器核数并不必然带来应用性能的提升,需要充分挖掘应用中的并行性以利用处理器的多核特性。在编译系统中挖掘并行性,具有对程序员透明、有可能在机器指令层面发挥硬件潜力等特点,因此当前的主流编译器(如GNU GCC、Intel ICC、IBM XLC和Oracle Compiler)均提供了对多核的支持和优化。
|
||
|
||
与多核处理器通常仅集成几个处理单元不同,众核处理器在同一处理器内部集成了大量同构处理单元。例如,GPU(Graphics Processing Unit)在一个芯片上集成数百甚至数千个“小而简单”的核心,通过使用大量线程并发提高性能,特别适合用于加速大规模并行应用。近年来,众核处理器在高性能计算、人工智能等领域发展迅速,其编译优化技术也随着体系结构的不断升级而进步,包括针对GPU不同存储层次的优化、程序并行度的自动调优、通信优化、针对宽向量的自动向量化等。
|
||
|
||
多核和众核处理器不断发展的同时,聚合两类处理器的异构计算平台获得了工业界和学术界的重视。2007年首个针对异构计算平台的通用编程模型OpenCL出现,各硬件厂商纷纷提供了OpenCL编译、运行时和驱动支持,使OpenCL代码能够运行在不同类型和不同厂商的硬件平台上。此外,OpenMP 4.0标准也引入了异构计算支持。目前,异构计算平台已成功运用到从超级计算机到移动设备的不同层次计算机系统中。
|
||
|
||
\section{中间件}\label{middleware}
|
||
“中间件(Middleware)”\index{中间件}本义是指位于操作系统之上、应用软件之下的一层中间软件,提供操作系统所不具备、但上层应用又迫切需要的系统软件功能。过去很长一段时间内,经典操作系统并未充分考虑分布式应用支撑问题,因此狭义的、或者说现代意义上的“中间件”往往特指网络计算中间件\index{网络计算中间件},即支持分布式应用的部署、运行和管理的软件\cite{mei2005middleware}。今天,随着应用软件和操作系统的发展,中间件一词含义也在不断演化(图\ref{fig:3-3}),并表现出沉淀和融入到操作系统中的趋势。
|
||
|
||
\begin{figure}[htbp]
|
||
\centering
|
||
\includegraphics[width=0.95\textwidth]{fig1-3/3-3.png}
|
||
\caption{中间件发展历程
|
||
\label{fig:3-3}}
|
||
\end{figure}
|
||
|
||
\subsection{早期的中间件}
|
||
中间件的出现是软件系统应用场景快速拓展的结果。随着计算技术的发展,上层应用在适应新场景过程中对系统软件不断提出新的要求,而作为底层支撑的经典操作系统能力相对稳定固化,很难快速跟上这些变化,二者之间的差距决定了中间件存在的合理性。在1968年北大西洋公约组织的软件工程报告中,“中间件”一词被首次使用\cite{buxton1970software},代指弥补底层操作系统(当时称“服务例程/控制程序”)通用能力和上层应用特化需求之间鸿沟的中间层软件(图\ref{fig:3-4})。1972年已经有文献指出:“随着一些系统变得空前复杂,标准的操作系统需要扩展或修改,推动了‘中间件’这一名词出现”\cite{jenkins1972developments}。
|
||
|
||
\begin{figure}[htbp]
|
||
\centering
|
||
\includegraphics[width=0.40\textwidth]{fig1-3/3-4.png}
|
||
\caption{NATO软件工程报告中的倒金字塔软件结构\cite{buxton1970software}
|
||
\label{fig:3-4}}
|
||
\end{figure}
|
||
|
||
虽然“中间件”这一名词在60年代中后期即已出现,但早期计算机厂商通常提供从操作系统到应用软件的一揽子解决方案,使得二者之间的鸿沟并不凸显。20世纪80年代初,网络技术走向成熟,如何高效构造跨越多个计算结点的分布式应用成为焦点。在传统操作系统之上,开发人员只能通过操作系统的Socket API原生接口,以完全手工方式实现分布式应用中的网络消息传递,其过程繁琐、复杂且低效。同时,除了通信支持外,相对于单机软件,分布式系统还有很多特有的理论和技术问题(如并发支持、事务管理、访问控制等),而传统操作系统并未提供相应的支撑能力。
|
||
|
||
为了应对上述挑战,人们早期围绕两种思路展开了探索。一是以Amobea\cite{Tanenbaum:1990:EAD:96267.96281}等分布式操作系统为代表的方法,核心是将单机操作系统的概念放大到网络环境,实现对网络软硬件资源的严格管控,例如文献\cite{Tanenbaum:1985:DOS:6041.6074}指出“分布式操作系统对用户而言与单机操作系统无二,只是运行在多个独立处理器上。它的核心概念是透明性”。但是,网络资源具有分布自治、高度异构、持续演化等特点,其软件很难通过严格的以自顶向下的方法精确设计出来,而更多的是通过互联互通方式成长式构造出来的。后一种思路在1976年的ARPANET RFC707中即以“允许调用远程进程所实现的任意命令或函数”的“请求-响应”协议形式出现\footnote{IETF, ``RFC 707 - High-level framework for network-based resource sharing,'' 1977}。Birrel和Nelson等于1984年实现了首个远程过程调用(Remote Procedure Call,RPC)\index{远程过程调用}框架\cite{Birrell:1984:IRP:2080.357392},这标志着现代意义中间件的诞生。
|
||
|
||
\subsection{面向内联网的中间件}
|
||
中间件在诞生之后的很长一段时间内,都以企业或组织内部的内联网(Intranet)为运行环境,为明确边界范围的域内资源互联互通提供系统软件支撑。如前所述,最早被广泛接受的此类中间件是面向过程中间件\index{面向过程中间件}。它们聚焦于尽量实现“调用远程过程像调用本地过程一样简单”,早期的Sun RPC、开源软件基金会的DCE(Distrbuted Computing Environment)和今天的Google gRPC、Apache Thrift等都是典型实例。
|
||
|
||
相对于过程,“对象”提供了更贴近现实世界的抽象。面向对象中间件\index{面向对象中间件}出现于上个世纪80年代初,例如华盛顿大学1980年启动的Eden项目\cite{Black:1985:SDA:323627.323646}即以在网络计算环境中应用面向对象技术为目标,提出了分布式Ejects(Eden objects)的概念、编程模型和相应支撑平台。OMG于1990年发布的CORBA 1.0是具有里程碑意义的面向对象中间件标准,它直接推动了面向对象中间件的成熟和高速发展,对后续SUN公司的Java/RMI、微软公司的DCOM等技术体系有着直接和深远的影响。
|
||
|
||
分别发布于1998年和2000年的EJB(Enterprise JavaBean)和CCM(CORBA Component Model)推动了面向构件中间件\index{面向构件中间件}的出现。面向构件中间件又被称为构件容器或构件化应用服务器,它是以构件为基本单元的分布式软件的运行平台。构件技术一方面强调通过大粒度、具有规范接口的软件单元来组装软件系统,另一方面由于构件具有规范的功能和管理接口,运行时可以对分布式系统进行灵活管理操纵,包括生命周期管理、交互关系管理甚至动态更新演化等。
|
||
|
||
除了上述支撑不同应用程序模型的通用中间件外,部份中间件关注的是分布式软件的一些特化场景,其典型代表是消息中间件\index{消息中间件}和事务处理中间件\index{事务处理中间件}:(1)在分布计算实践的初期,人们就已发现紧耦合、同步的过程调用并不能满足所有应用场合,支持异步交互和松耦合通信的分布式应用消息机制的研究和实践开始被重视,诸如Field、InformationBus等消息中间件平台开始出现。上个世纪90年代,IBM MQSeries等消息中间件产品被大量使用,消息中间件技术走向成熟。(2)在大型主机时代,IBM的CICS(Customer Information Control System)系统就已提供了跨计算结点事务支持。针对美国电话公司需要的联机事务处理能力,贝尔实验室于上个世纪80年代初发布了跨平台的Tuxedo事务处理中间件,相关研究与实践对后续X/Open组织的分布式事务处理规范、OMG组织的对象事务服务规范等产生了较大影响\cite{Emmerich:2008:IRD:13487689.13487692}。
|
||
|
||
\subsection{面向互联网的中间件}\label{internet-middleware}
|
||
20世纪90年代中后期, 互联网进入高速发展阶段。互联网资源具有开放动态、成长自治的特点,但人们同时又希望软件能够持续在线、高度可用,二者之间的矛盾催生了“服务”的概念。从2000年左右W3C组织所制定一系列Web Service标准开始,“服务”\index{服务}一词即被用来描述可通过网络按需访问、无需关心实现细节的软件实体。以“服务”为核心,面向服务体系结构(Service-Oriented Architecture,SOA)通过服务化和“服务提供者-消费者”之间的动态发现,在开放动态的互联网环境下提供可按需使用的软件能力。
|
||
|
||
作为互联网时代的产物,服务化思想首先推动了中间件技术外延的拓展。Apache Tomcat、IBM WebSphere等Web服务中间件以支撑面向服务体系结构为目标,封装了服务注册、服务发现、服务访问等共性基础设施;以企业服务总线(Enterprise Service Bus,ESB)\index{企业服务总线}为代表的服务集成中间件通过服务封装、服务组合、服务协同等技术实现自治子系统之间的通信,进而实现复杂业务系统跨域集成;微服务\index{微服务}则聚焦单个业务系统内部,通过系统内部组件的彻底服务化,实现开发阶段“分而治之”和运行阶段的灵活应变,这一思路催生了Spring Cloud等微服务框架。
|
||
|
||
近年来,作为服务化思想的集大成者,云计算模式被广泛接受。如同工业革命让水、电、交通等成为公共服务一样,云计算正在通过后端资源集约化和前端按需服务方式,推动信息技术实现社会化和专业化,使得信息服务成为公共基础设施。这一趋势推动着中间件概念内涵和外延的发展,新一代“平台即服务”(Platform as a Service, PaaS)软件基础设施成为了各大云服务提供商的核心竞争力所在。它为云端分布式应用提供服务化的、可按需使用的运行托管环境,集成了包括分布式调用、数据库访问、服务治理等在内的一系列软件栈,其典型代表包括Google AppEngine、Microsoft Azure、Amazon EC2等。与传统中间件相比,它们具有如下一些显著特征:
|
||
|
||
\begin{itemize}
|
||
\item 在资源的管控方面,此类平台的核心是大型主机时代即已出现的虚拟化技术,但将其应用场景拓展到了数据中心甚至多数据中心级别的,通过虚拟化实现海量计算、网络、存储资源的细粒度管理,进而实现资源的有效聚合和弹性扩展。例如,互联网虚拟计算环境 iVCE\cite{Lu:2013:IVC:2388122.2388238}通过资源的“自主协同、按需聚合”,将静态统一视图的资源组织模式扩展为相对稳定视图、按需可伸缩的资源组织模式,从而实现面向互联网计算的高效管控。
|
||
\item 在应用软件的执行管控维度上,此类平台面向云服务这类大规模分布计算软件,提供了任务调度与执行、负载均衡、安全管控、在线监控和升级演化、分布式数据存储访问等一系列基础设施和相应能力。这些能力以服务的方式提供,用户无需像传统系统软件那自行安装、部署和维护。部分“平台即服务”基础设施还内建了编译系统和调试/测试环境,支持云端开发和编译构建。
|
||
\item 在可用性方面,此类平台需要7×24小时持续提供基础服务,是支撑整个信息空间持续运行的核心基础设施,突出表现为一旦发生故障,会产生较大的社会经济影响。例如,有文献指出如果一个主要的云平台宕机3-6天,美国经济会产生30亿-150亿美元的损失\footnote{``Cloud Down: Impacts on the US economy,'' https://www.lloyds.com/\~/media/files/news-and-insight/risk-insight/2018/cloud-down/aircyberlloydspublic2018final.pdf}。
|
||
\end{itemize}
|
||
|
||
\subsection{人机物融合中间件}\label{blockchain-history}
|
||
计算技术的网络化和普适化推动了信息与物理空间的持续融合,出现了各类可以感知/作用于物理世界的大规模网络软件,中间件技术随之不断发展。本世纪初,随着相关硬件技术的逐渐成型,中间件领域针对嵌入式传感器和移动设备等载体,开始关注对物理空间情境(Context)数据的处理,出现了普适计算中间件、传感器网络中间件、情境感知中间件等一系列新型中间件。近年来快速发展的物联网中间件\index{物联网中间件}(IoT Middleware)在上述中间件概念的基础上,进一步针对“万物互联”的大规模异构环境进行了拓展,其核心关注点是在资源受限、高度异构、规模庞大、网络动态变化条件下,如何实现互联互通互操作,并且不违反各种时空约束特性,满足物联网应用对海量传感器数据或事件实时处理的需求。
|
||
|
||
除了感知物理世界外,随着信息物理融合系统的成熟,近年来中间件领域开始关注如何联接能够直接“作用”于物理世界的计算设备,其突出代表是无人系统/机器人中间件。针对无人系统计算环境高度异构、资源受限、常态失效、实时性要求高等特点,从2000年左右的Player等中间件开始,包括Miro、CLARAty、OpenRTM-aist、Pyra、Orca、MARIE等在内的一系列实践推动了无人系统中间件技术的发展,并直接为今天广泛使用的机器人“元级操作系统”ROS(Robot Operating System)奠定了理论和技术基础。
|
||
|
||
此外,从早期的P2P中间件到今天的区块链平台,分布自治中间件突出体现了“社会-技术”系统的思想,具有人机融合的特点。此类中间件通过信息空间内的机制设计激励人的自主协同,通过软件基础设施及平台支撑社会价值交换。以区块链为例,2009年比特币网络上线并持续无故障运行,2010年“比特币披萨日”第一次用于购买实物,2013年塞浦露斯金融危机中比特币成功得到高度关注。从软件角度而言,此时的比特币仍然只是一个独立于国家货币体系的分布式应用,而2014年发布的以太坊则摆脱了电子货币的桎梏:作为建立于区块链技术之上的应用平台,以太坊的“区块”可以记录各类数据,而Solidity语言描述的智能合约能够实现各种场景下的复杂应用逻辑。这标志着区块链从应用层技术向支持分布式共识的系统软件部件的转变。后续超级帐本、联盟链等技术/系统的发展,更进一步将参与方从个人扩展到组织,在金融、物流、社会治理等领域形成了一系列极具前景的新型应用模式。
|
||
|
||
\section{数据库管理系统}
|
||
数据库\index{数据库}是长期存储在计算机内有组织、可共享的大量数据的集合,数据库管理系统旨在统一管理和维护数据库中的数据,是组织、存储、存取、控制和维护数据的软件。从本质上而言,数据库管理系统\index{数据库管理系统}把逻辑数据转换成为计算机中具体的物理数据,从而使得用户可以访问、检索和维护数据,而不必顾及这些数据在计算机中的布局和物理位置。
|
||
|
||
数据库管理系统的发展历史可以按照其支撑的应用特征来划分(图\ref{fig:3-5})\cite{du2019bigdata}。第一代系统主要是支持数据的存储与访问,数据的组织以层次和网状模型为代表。第二代系统主要围绕联机事务处理(Online Transaction Processing,OLTP)应用展开,在关系模型和存储技术的基础上,重点发展了事务处理、查询优化等能力。第三代系统主要围绕联机分析处理(Online Analysis Processing,OLAP)应用展开,重点在于提出高效支持联机分析处理复杂查询的新型数据组织技术。第四代系统主要围绕大数据应用展开,重点在分布式可扩展、异地多备份高可用架构、多数据模型支持、以及多应用负载类型支持等特性。
|
||
|
||
\begin{figure}[htbp]
|
||
\centering
|
||
\includegraphics[width=0.75\textwidth]{fig1-3/3-5.png}
|
||
\caption{数据库管理系统发展历程
|
||
\label{fig:3-5}}
|
||
\end{figure}
|
||
|
||
\subsection{层次和网状数据库}
|
||
20世纪50年代前期,计算机被主要用于科学计算,数据仅被认为是“计算”的产品或附属品,通常存储在被称为“文件”的打孔卡片(早期)或外设数据单元上。随着计算机应用领域向商业、金融、政府等通用领域扩展,文件作为数据存储的主要设施,已经无法满足对各类应用中数据项之间的复杂关系进行管理的需求,主要表现在以下几个方面:文件内部数据组织往往是面向单一应用的,不同应用共享同一个文件结构效率较低;文件之间的数据是独立的,无法表达两个文件的数据所存在内在逻辑关系;文件的组织方式单一,难以满足不同的访问模式对数据高效率访问的需求。
|
||
|
||
在上述背景下,为了提供系统化、高效的数据组织与访问功能,专门的数据库管理系统开始出现。60年代初通用电气在其生产信息和控制系统(MIACS)中设计了“集成数据存储”(Integrated Data Store),被认为是首个支持直接访问的数据库管理系统\cite{Bachman:2009:OID:1674526.1674536},并直接为CODASYL组织后续制定的网状数据库标准奠定了基础。1968年,IBM发布了运行于System/360主机的层次数据库管理系统IMS(Information Management System)。上述两个具有里程碑意义的产品分别代表了数据库管理系统的两种早期数据模型,也即数据是按照网状的“图”还是层次化的“树”来组织。其中,层次模型由于其每一个节点最多只有一个父节点,因此可以采用有效的手段(例如按照树遍历的顺序)来存储数据,而网状模型可以将图分解为一组“基本层次联系”的集合,其本质上可以用“树”结构来表达和存储数据。
|
||
|
||
\subsection{关系数据库}
|
||
20世纪70年代是关系数据库\index{关系数据库}形成并实现产品化的年代。1970年,IBM的Edgar F. Codd发表题为“大型共享数据库的关系模型”的论文\cite{Codd:1970:RMD:362384.362685},文中提出了数据库的关系模型。由于关系模型简单明了、具有坚实的数学理论基础,操作语言是描述性的,无需像层次网状模型那样,需要描述存取路径(既先访问哪个数据再访问哪个数据)这样的细节,给提高信息系统开发的生产率提供了极大的空间,所以一经提出就受到了学术界和产业界的高度重视和广泛响应。尽管一开始产业界还充斥着对关系数据库系统性能的怀疑,但IBM所开发的System R系统证明了其性能可以有保障。这一结论极大地推动了关系数据库技术的发展,关系数据库产品开始涌现,包括IBM公司在System R系统基础上推出的DB2产品、ORACLE公司的同名数据库产品,以及80年代初出现的、针对个人电脑设计的dBase等。由于Edgar F. Codd的杰出贡献,1981年的图灵奖授予了这位“关系数据库之父”。
|
||
|
||
20世纪80年代,关系数据库迅速取代层次和网状数据库占领市场,数据库领域相关研究工作也转为以关系数据库为主,主要包括查询优化和事务管理等方面:(1)查询优化。关系数据库语言是基于集合的描述性语言(如70年代初出现的SQL语言),其查询的结果也是一个集合。如何将一个SQL语句转换为可以执行的程序(类似程序自动生成器),而且要在所有可能的执行计划(程序)中选择出一个效率足够好的加以执行,是这一阶段工作重点之一。(2)事务管理。事务管理提供对并发事务的调度控制和故障恢复能力,是确保大规模数据库系统正确运行的基石,相关研究工作为数据库管理系统成熟并顺利进入市场做出了重要的贡献。
|
||
|
||
\subsection{数据仓库系统}
|
||
数据仓库\index{数据仓库}可看作是关系数据库的自然延伸。随着数据库技术的普及应用,越来越多的数据被存储在数据库中,除了支持业务处理以外,如何让这些数据发挥更大的作用,就是一个亟待解决的问题。特别是对于联机分析处理类应用,如何让复杂分析能高效地执行,需要有特殊的数据组织模式,这就推动了数据仓库系统的出现。
|
||
|
||
星型模型是最常用的数据仓库的数据组织模型。所谓星型模型也称多维模型,就是选定一些属性作为分析的维度,另一些属性作为分析的对象。维属性通常根据值的包含关系会形成一个层次,例如时间属性可以根据年月周日形成一个层次,地区属性也可以形成街道-区-市这样的层次。为了实现快速分析,可以预先计算出不同层次上的统计结果,从而获得快速联机分析的性能。在实现方式上,数据仓库可以用关系数据库实现(Relational OLAP),分别用事实表和维表来存储统计结果和维度结构,也可以用特别的数据模型(CUBE)来实现,列存储的技术也在这个过程中被提出和应用。同时,支持联机分析处理的前端工具的发展,也使得普通用户可以方便地使用数据仓库
|
||
|
||
\subsection{大数据时代的数据库管理系统}
|
||
关系数据库成熟并广泛应用后,数据库领域一度走入一段迷茫期,被关系模型的“完美”所陶醉。进入21世纪,互联网的高速发展使得数据规模越来越庞大,传统关系数据库的弊端开始凸显:在搜索引擎、流媒体等拥有海量非结构化数据的领域,传统的关系数据模型并不完全适用,而关系型数据库所承诺的原子性、一致性、隔离性、持久性等ACID特性在这些领域有可能不需要严苛保证,不必要的开销和有限的可扩展性导致数据存储和管理效率低下。在这一背景下,NoSQL数据库\index{NoSQL数据库}开始出现,其重要的里程碑事件是Google所发布的Bigtable\cite{Chang:2008:BDS:1365815.1365816}及根据其理念所开发的开源HBase数据库。与关系数据库不同,NoSQL数据库不再采用严苛的关系模型,转而使用更为灵活的键值对结构、文档模型、图模型等。同时,NoSQL数据库可能不提供严格的一致性保证,并且通常在设计时即考虑了水平可扩展能力(即通过增加计算节点来扩充处理能力),因此可以达到比关系型数据库更高容量和性能。
|
||
|
||
随着实践的深入,人们发现NoSQL并非解决大数据时代数据管理问题的“银弹”。一方面,无论从应用程序继承的角度还是提高生产率的角度,SQL语言都是不可或缺的工具,因此继承和汲取SQL的优点(如在上层提供SQL查询引擎)逐渐成为NoSQL数据库的共识,NoSQL一词的含义也从“非SQL”被修正为“不仅仅是SQL”(Not Only SQL)。另一方面,许多联机事务处理业务在应对海量数据同时仍需要采用关系模型,并保证原子性、一致性、隔离性、持久性等特性。因此,能够提供与NoSQL数据库类似的扩展性能、但仍具备关系数据库能力的NewSQL数据库\index{NewSQL数据库}近年来得到了快速发展,其典型代表包括Google全球级分布数据库Spanner\cite{Corbett:2013:SGG:2518037.2491245}和开源领域的CockroachDB、TiDB等。
|
||
|
||
\section{本章小结}
|
||
系统软件将计算系统的概念从硬件扩展到了软件层面上,它为上层应用提供了一个可以使用各类资源能力、但又无需关注底层细节的软件平台。历经六十余年的发展,系统软件已经形成操作系统、编译系统、中间件和数据库管理系统等典型形态,已经成为了计算机软硬件生态链的核心,对信息产业乃至人类社会产生了较大影响,在促进经济发展和文明进步中发挥了重要作用。在这一过程中,系统软件表现出了如下一些发展规律:
|
||
|
||
\begin{itemize}
|
||
\item 硬件技术和应用场景变迁是发展的核心动力。系统软件具有“承上启下”的特点,无论是形态还是机理的发展都受到硬件和应用两方面的驱动。例如,如贝尔定律所述,计算设备约每10年一次换代,设备和用户增加10倍,成为新的蓝海、催生新型应用,间次推动操作系统换代并形成新的生态,使得操作系统每隔20年左右迎来一次跨越式发展的机遇期(参见图\ref{fig:3-1})。另一个典型案例是编译系统:近年来高性能计算、智能计算方面的应用需求,以及GPU等新型硬件的出现,成为了编译系统近年来发展的主要动力。
|
||
\item 构建“抽象”和实现平台化是发展的重要主题。本质而言,系统软件负责向应用提供运行支撑、网络交互、数据管理等不同维度上的“抽象”,并将这些“抽象”以尽可能高效方式绑定到硬件裸机,充分发挥硬件潜力。例如,过去数十年中,操作系统形成了一系列诸如文件、进程/线程、内存页、Socket等的概念,并由这些概念实体共同组成了支撑应用运行、区别于真实物理机器的虚拟机器。同时,沉淀共性、进而实现平台化也是系统软件发展的重要主题,它一方面可以避免应用去重新“造每一个轮子”,另一方面也为软件生态的良性发展奠定基础。
|
||
\item 技术螺旋上升与交叉融合是发展的主要特征。与应用软件的快速更新不同,系统软件具有相对稳定性,很多核心技术表现出了螺旋上升的特点。例如,虚拟化技术早在60年代IBM实验性操作系统CP-40和其后商用化的CP-67、VM/370中得到完整实现,而云计算时代虚拟化技术“复兴”过程中的挑战则主要来自于数据中心环境资源集约化的需求。另一方面,系统软件发展经历了从无到有、进而形成多个分支的过程。“分久必合”,近年来分支之间表现出相互融合趋势,中间件与操作系统就是一个典型案例(参见\ref{middleware}节)。
|
||
\end{itemize}
|