操作系统(OS)
有特殊权限可以操作硬件
运行和管理其它程序
批处理:一次读取多个程序,运行完一个后自动运行下一个
设备驱动程序,充当软硬件间的媒介
多任务处理
虚拟内存
动态内存分配
内存保护
设备驱动程序
不同计算机配置不同,又连着各种不同的外设,早期程序员必需了解设备硬件细节才能写程序,进而导致程序员需要拿到所有型号的硬件设备来测试代码。
设备驱动程序:操作系统提供 API 来抽象硬件,使得程序员可以通过标准化机制和 I/O 硬件交互。
多任务处理
到 1950 年代末,电脑已经非常快了,处理器经常闲着等待慢的机械设备(比如打印机和读卡器),程序便阻塞在了 I/O 上。
1962 年开发完成的 Atlas Supervisor 通过调度实现了在单个 CPU 上同时运行多个程序。
以需要打印数据的程序 A 和无需进行 I/O 操作的程序 B 举列
Atlas 运行程序 A 直至需要打印数据
Atlas 将需要打印的数据和打印命令发给打印机后就将程序 A 挂起
Atlas 转而去运行程序 B
打印机打印完数据后通知 Atlas
Atlas 将程序 B 挂起,回来继续运行程序 A 至其结束
注:这里的多任务处理就是常说的并发。
虚拟内存
多个程序运行在单个 CPU 上时,每个程序都会占一些内存,当切换程序时,我们不能丢失数据。解决办法是给每个程序分配专属内存。
由操作系统决定每个程序分配多大的内存块、分配在那个位置。但这带来了一个问题“程序 A 可能被分配到非连续的内存块”。
为了隐藏和抽象这种程序在内存实际物理位置上分配的复杂性,操作系统把内存的地址进行“虚拟化”,即虚拟内存。
借助虚拟内存,程序可以假定内存总是从地址 0 开始。
虚拟内存机制使程序的内存大小可以灵活增减,即动态内存分配。对程序来说,内存看起来总是连续的,为多任务处理提供了极大的灵活性。
给程序分配专用的内存范围,另一个好处就是更好隔离程序。一个程序出错只会捣乱它自己的内存,不会影响到其它程序,即内存保护。内存保护还可以用来防止恶意软件。
多用户分时操作系统
1970 年代,计算机足够便宜,大学买了让学生用,多个学生用多个终端连接到主机。这就需要操作系统不但要同时处理多个程序,还要处理多个用户,操作系统便进化到了分时操作系统。
分时操作系统:每个用户只能用一小部分处理器、内存等,因为电脑足够快,即使拿到 1/50 的资源也足以完成许多任务。
1969 年发布的 Multics 是早期影响力最大的分时操作系统,也是第一个从设计时就考虑到安全的操作系统。
Unix
Multics 的研究员之一 Dennis Ritchie 曾说“阻碍 Multics 获得商业成功的一个明显问题是,从某方面来说,它被过度设计了,功能太多了”。
所以 Dennis 和另一个 Multics 的研究员 Ken Thompson 联手打造了 Unix,他们想把操作系统分为两部分:
操作系统的核心功能:内存管理,多任务和 I/O 处理,即 kernel(内核)
一堆有用的工具:程序和运行库
Dennis 在设计 Unix 时大胆的提出了 kernel panic(内核恐慌)的概念:大幅减少错误恢复代码,有错误发生,就调用 panic 函数让设备崩溃。
因为 Unix 的简单性,使其能在更多更便宜的硬件上运行,也使其在 Dennis 和 Ken 工作的贝尔实验室大受欢迎,工具数量日益增长。从 1971 年发布后不久,就有人写了不同编程语言的编译器和文字处理器。
MS-DOS
微软的磁盘操作系统 MS-DOS 于 1981 年发布,成为早期家用电脑最受欢迎的 OS。
MS-DOS 的一大问题是其缺少多任务和内存保护功能,直到微软 1985 年发布的早期 Windows(在 90 年代很流行)都依然缺乏内存保护。一旦程序运行不当就会蓝屏,代表程序崩溃得非常严重,以致把系统也带崩溃了。