Skip to content
On this page

导论

今天看看《操作系统导论》,至于之前的坑?慢慢填吧~

程序运行时干了什么

这书满是干货,基本不废话,分章节还是有点困难的样子,如果你看到某些特别怪的排版请谅解。

一个正在运行的程序会做一件非常简单的事情:执行指令。从内存中获取一个指令,对其解码,然后执行(像是两数相加、检查条件、访问内存),完成这条指令后,处理器继续执行下一条指令,依次类推,知道程序最终完成。

操作系统概览

有一类软件负责让程序运行变得容易(甚至允许你同时运行多个程序),允许程序共享内存,让程序跟设备交互,以及其他类似的工作。这类软件被称为操作系统。

为了实现这一点,操作系统主要利用一种通用的技术,我们称之为虚拟化,也就是说,操作系统将物理资源转换为更通用、更强大的虚拟形式,因此我们有时称操作系统为虚拟机。

当然,为了让用户可以告诉操作系统做什么,从而利用虚拟机的功能,供你调用,操作系统还提供了一些接口 API 供你调用,典型的操作系统会提供数百个系统调用,所以我们有时候会说操作系统为应用程序提供了一个标准库。

虚拟化

虚拟化 CPU

尽管我们的电脑只有一个处理器,但是为什么所有程序似乎在同时运行呢?这是因为在硬件帮助下,操作系统负责提供了拥有很多虚拟 CPU 的假象,将单个 CPU 转换为看似无限数量的 CPU。

然而一次运行多个程序的能力会引发各种新问题,例如两个程序想在特定时间运行,应该运行哪个?这个问题由操作系统的策略回答,因此操作系统承担了资源管理器的角色。

虚拟化内存

现代机器提供的物理内存模型非常简单,内存就是一个字节数组,要读取内存,必须指定一个地址,才能读取内存及存储在那里的数据,要写入或是更新内存,还必须指定要写入给定地址的数据。

程序运行时,一直要访问内存。程序将所有数据结构保存在内存中,并通过各种指令来访问他们,例如加载和保存,或利用其他明确的指令,在工作时访问内存。

cpp
// 没学过 c 系列语言,这里是摘录书里的代码的片段,如果有错请多见谅
// int main...
int *p = malloc(sizeof(int));
assert(p != NULL);
printf("(%d) memory address of p: %08x\n", getpid(), (unsigned) p);
shell
$ ./mem && ./mem
(23411) memory address of p: 00200000
(23412) memory address of p: 00200000

似乎每个正在运行的程序都在相同的内存地址分配了内存,但是实际上占用的是不同的物理内存,就像是每个程序都有自己的私有内存,而不是跟其他正在运行的程序共享相同的物理内存。

并发

操作系统有一系列问题,这些问题是操作系统在处理很多事情的时候出现并且必须解决,比如上面虚拟化的例子中,操作系统同时处理很多件事情,这样做灰导致一些深刻的问题。

持久性

在系统内存中,数据容易丢失,如果断电崩溃,内存中的所有数据都会丢失,因此我们需要硬件和软件持久地保存数据。

操作系统中管理磁盘的软件通常称作文件系统。因此它负责以可靠和高效的方式将用户创建的文件存储在系统的磁盘上。

然而跟内存不同的是,操作系统并没有给所有程序提供虚拟化磁盘,相反,它假设用户需要共享文件中的信息。

为了读取文件,程序向操作系统发出三个调用,第一个是 open(),它打开文件或创建它,第二个是 write(),将一些数据写入文件,第三个是 close(),只是简单的关闭文件。这些系统调用被转到操作系统的文件系统部分。

操作系统的设计目标

现在我们了解了操作系统实际上干了什么:取得 CPU、内存、磁盘等物理资源,并进行虚拟化,处理关于并发有关的麻烦且棘手的问题,并持久地存储文件,从而使他们长期安全。我们希望建立这么一个系统,所以要有一些目标,以帮助我们集中设计和实现,并在必要的时候折中。

  1. 建立一些抽象,让系统方便和利于使用
  2. 提供高性能
  3. 在应用程序之间及 OS 和应用程序之间提供保护。

后话

现在看一些编程语言进阶的书已经很吃力了,感觉是基础太差了,太难受了,于是就准备补点操作系统和语言设计方面的玩意看看。

Released under the MIT License.