龙空技术网

操作系统领域里的自学神作是这本书

程序员荐书 2076

前言:

现在你们对“c语言开发操作系统必读书籍”大约比较注重,兄弟们都需要学习一些“c语言开发操作系统必读书籍”的相关知识。那么小编也在网摘上搜集了一些有关“c语言开发操作系统必读书籍””的相关文章,希望你们能喜欢,你们快快来了解一下吧!

操作系统领域里的自学神作是这本书!

操作系统导论

《操作系统导论》在豆瓣的评分9.4,好多读过的书友建议大家坚持读完,会有意想不到的进步与收获。

豆瓣评论节选:

写的很好,深入浅出地介绍了操作系统的核心内容,值得推荐

这是我在操作系统领域里读过最好的书了。整体循序渐进,参考资料质量也很高。

涉及到操作系统的虚拟化技术,并发和存储系统,另外还包括丰富的参考资料,程序员必读书籍之一,值得二读。

本书围绕3个主题展开讲解:虚拟化(virtualization)、并发(concurrency)和持久性(persistence)。对于这些概念的讨论,最终延伸到讨论操作系统所做的大多数重要事情。希望你在这个过程中体会到一些乐趣。学习新事物很有趣,对吧?

每个主要概念在若干章节中加以阐释,其中大部分章节都提出了一个特定的问题,然后展示了解决它的方法。这些章节很简短,尝试(尽可能地)引用作为这些想法真正来源的源材料。我们写这本书的目的之一就是厘清操作系统的发展脉络,因为我们认为这有助于学生更清楚地理解过去是什么、现在是什么、将来会是什么。在这种情况下,了解香肠的制作方法几乎与了解香肠的优点一样重要。

我们在整本书中采用了几种结构,值得在这里介绍一下。

无论何时,在试图解决问题时,我们首先要说明最重要的问题是什么。我们在书中明确提出关键问题(crux of the problem),并希望通过本书其余部分提出的技术、算法和思想来解决。

在许多地方,我们将通过显示一段时间内的行为来解释系统的工作原理。这些时间线(timeline)是理解的本质。如果你知道会发生什么,例如,当进程出现页故障时,你就可以真正了解虚拟内存的运行方式。如果你理解日志文件系统将块写入磁盘时发生的情况,就已经迈出了掌握存储系统的第一步。

整本书中有许多“补充”和“提示”,为主线讲解增添了一些趣味性。“补充”倾向于讨论与主要文本相关的内容(但可能不是必要的);“提示”往往是一般经验,可以应用于所构建的系统。

在整本书中,我们使用最古老的教学方法之一——对话(dialogue)。这些对话用于介绍主要的主题概念,并不时地复习这些内容。这也让我们得以用更幽默的方式写作。好吧,你觉得它们是有用还是幽默,完全是另一回事。

在每一个主要部分的开头,我们将首先呈现操作系统提供的抽象(abstraction),然后在后续章节中介绍提供抽象所需的机制、策略和其他支持。抽象是计算机科学各个方面的基础,因此它在操作系统中也是必不可少的。

在所有的章节中,我们尝试使用真实代码(real code),而非伪代码(pseudocode)。因此书中几乎所有的示例,你应该能够自己输入并运行它们。在真实系统上运行真实代码是了解操作系统的最佳方式,因此建议你尽可能这样做。

在本书的各个部分,我们提供了一些作业(homework),确保你进一步理解书中的内容。其中许多作业都是对操作系统的一些模拟(simulation)程序。你应该下载作业,并运行它们,以此来测验自己。作业模拟程序具有以下特征:通过给它们提供不同的随机种子,你可以产生几乎无限的问题,也可以让模拟程序为你解决问题。因此,你可以一次又一次地自测,直至很好地理解了这些知识。

本书最重要的附录是一组项目(project),可供你通过设计、测试和实现自己的代码,来了解真实系统的工作原理。所有项目(以及上面提到的代码示例)都是使用C编程语言(C programming language)[KR88]编写的。C是一种简单而强大的语言,是大多数操作系统的基础,因此值得添加到你的工具库中。附录中含有两种类型的项目(请参阅在线附录中的想法)。第一类是系统编程(system programming)项目。这些项目非常适合那些不熟悉C和UNIX,并希望学习如何进行底层C编程的人。第二类基于在麻省理工学院开发的实际操作系统内核,称为xv6 [CK+08]。这些项目非常适合已经有一些C的经验并希望深入研究操作系统的学生。在威斯康星大学,我们以 3 种不同的方式开课:系统编程、xv6编程,或两者兼而有之。

操作系统的开发历史

早期操作系统:只是一些库

一开始,操作系统并没有做太多事情。基本上,它只是一组常用函数库。例如,不是让系统中的每个程序员都编写低级I/O处理代码,而是让“OS”提供这样的API,这样开发人员的工作更加轻松。

通常,在这些老的大型机系统上,一次运行一个程序,由操作员来控制。这个操作员完成了你认为现代操作系统会做的许多事情(例如,决定运行作业的顺序)。如果你是一个聪明的开发人员,就会对这个操作员很好,这样他们可以将你的工作移动到队列的前端。

这种计算模式被称为批(batch)处理,先把一些工作准备好,然后由操作员以“分批”的方式运行。此时,计算机并没有以交互的方式使用,因为这样做成本太高:让用户坐在计算机前使用它,大部分时间它都会闲置,所以会导致设施每小时浪费数千美元[BH00]。

超越库:保护

在超越常用服务的简单库的发展过程中,操作系统在管理机器方面扮演着更为重要的角色。其中一个重要方面是意识到代表操作系统运行的代码是特殊的。它控制了设备,因此对待它的方式应该与对待正常应用程序代码的方式不同。为什么这样?好吧,想象一下,假设允许任何应用程序从磁盘上的任何地方读取。因为任何程序都可以读取任何文件,所以隐私的概念消失了。因此,将一个文件系统(file system)(管理你的文件)实现为一个库是没有意义的。实际上,还需要别的东西。

因此,系统调用(system call)的概念诞生了,它是Atlas计算系统[K+61,L78]率先采用的。不是将操作系统例程作为一个库来提供(你只需创建一个过程调用(procedure call)来访问它们),这里的想法是添加一些特殊的硬件指令和硬件状态,让向操作系统过渡变为更正式的、受控的过程。

系统调用和过程调用之间的关键区别在于,系统调用将控制转移(跳转)到OS中,同时提高硬件特权级别(hardware privilege level)。用户应用程序以所谓的用户模式(user mode)运行,这意味着硬件限制了应用程序的功能。例如,以用户模式运行的应用程序通常不能发起对磁盘的I/O请求,不能访问任何物理内存页或在网络上发送数据包。在发起系统调用时 [通常通过一个称为陷阱(trap)的特殊硬件指令],硬件将控制转移到预先指定的陷阱处理程序(trap handler)(即预先设置的操作系统),并同时将特权级别提升到内核模式(kernel mode)。在内核模式下,操作系统可以完全访问系统的硬件,因此可以执行诸如发起I/O请求或为程序提供更多内存等功能。当操作系统完成请求的服务时,它通过特殊的陷阱返回(return-from-trap)指令将控制权交还给用户,该指令返回到用户模式,同时将控制权交还给应用程序,回到应用离开的地方。

多道程序时代

操作系统的真正兴起在大主机计算时代之后,即小型机(minicomputer)时代。像数字设备公司(DEC)的PDP系列这样的经典机器,让计算机变得更加实惠。因此,不再是每个大型组织拥有一台主机,而是组织内的一小群人可能拥有自己的计算机。毫不奇怪,这种成本下降的主要影响之一是开发者活动的增加。更聪明的人接触到计算机,从而让计算机系统做出更有趣和漂亮的事情。

特别是,由于希望更好地利用机器资源,多道程序(multiprogramming)变得很普遍。操作系统不是一次只运行一项作业,而是将大量作业加载到内存中并在它们之间快速切换,从而提高CPU利用率。这种切换非常重要,因为I/O设备很慢。在处理I/O时让程序占着CPU,浪费了CPU时间。那么,为什么不切换到另一份工作并运行一段时间?

在I/O进行和任务中断时,要支持多道程序和重叠运行。这一愿望迫使操作系统创新,沿着多个方向进行概念发展。内存保护(memory protection)等问题变得重要。我们不希望一个程序能够访问另一个程序的内存。了解如何处理多道程序引入的并发(concurrency)问题也很关键。在中断存在的情况下,确保操作系统正常运行是一个很大的挑战。我们将在本书后面研究这些问题和相关主题。

当时主要的实际进展之一是引入了UNIX操作系统,主要归功于贝尔实验室(电话公司)的Ken Thompson和Dennis Ritchie。UNIX从不同的操作系统获得了许多好的想法(特别是来自Multics [O72],还有一些来自TENEX [B+72]和Berkeley分时系统[S+68]等系统),但让它们更简单易用。很快,这个团队就向世界各地的人们发送含有UNIX源代码的磁带,其中许多人随后参与并添加到系统中。请参阅补充了解更多细节[10]。

摩登时代

除了小型计算机之外,还有一种新型机器,便宜,速度更快,而且适用于大众:今天我们称之为个人计算机(Personal Computer,PC)。在苹果公司早期的机器(如Apple II)和IBM PC的引领下,这种新机器很快就成为计算的主导力量,因为它们的低成本让每个桌子上都有一台机器,而不是每个工作小组共享一台小型机。

遗憾的是,对于操作系统来说,个人计算机起初代表了一次巨大的倒退,因为早期的系统忘记了(或从未知道)小型机时代的经验教训。例如,早期的操作系统,如DOS(来自微软的磁盘操作系统),并不认为内存保护很重要。因此,恶意程序(或者只是一个编程不好的应用程序)可能会在整个内存中乱写乱七八糟的东西。第一代macOS(V9及更早版本)采取合作的方式进行作业调度。因此,意外陷入无限循环的线程可能会占用整个系统,从而导致重新启动。这一代系统中遗漏的操作系统功能造成的痛苦列表很长,太长了,因此无法在此进行全面的讨论。

幸运的是,经过一段时间的苦难后,小型计算机操作系统的老功能开始进入台式机。例如,macOS X的核心是 UNIX,包括人们期望从这样一个成熟系统中获得的所有功能。Windows在计算历史中同样采用了许多伟大的思想,特别是从Windows NT开始,这是微软操作系统技术的一次巨大飞跃。即使在今天的手机上运行的操作系统(如Linux),也更像小型机在20世纪70年代运行的,而不像20世纪80年代PC运行的那种操作系统。很高兴看到在操作系统开发鼎盛时期出现的好想法已经进入现代世界。更好的是,这些想法不断发展,为用户和应用程序提供更多功能,让现代系统更加完善。

补充:UNIX的重要性 

在操作系统的历史中,UNIX的重要性举足轻重。受早期系统(特别是MIT著名的Multics系统)的影响,UNIX汇集了许多了不起的思想,创造了既简单又强大的系统。

最初的“贝尔实验室”UNIX的基础是统一的原则,即构建小而强大的程序,这些程序可以连接在一起形成更大的工作流。在你输入命令的地方,shell提供了诸如管道(pipe)之类的原语,来支持这样的元(meta-level)编程,因此很容易将程序串起来完成更大的任务。例如,要查找文本文件中包含单词“foo”的行,然后要计算存在多少行,请键入:grep foo file.txt | wc -l,从而使用grep和wc (单词计数)程序来实现你的任务。

UNIX环境对于程序员和开发人员都很友好,并为新的C编程语言提供了编译器。程序员很容易编写自己的程序并分享它们,这使得UNIX非常受欢迎。作为开放源码软件(open-source software)的早期形式,作者向所有请求的人免费提供副本,这可能帮助很大。

代码的可得性和可读性也非常重要。用C语言编写的美丽的小内核吸引其他人摆弄内核,添加新的、很酷的功能。例如,由Bill Joy领导的伯克利创业团队发布了一个非常棒的发行版(Berkeley Systems Distribution,BSD),该发行版拥有先进的虚拟内存、文件系统和网络子系统。Joy后来与朋友共同创立了Sun Microsystems。

遗憾的是,随着公司试图维护其所有权和利润,UNIX的传播速度有所放慢,这是律师参与其中的不幸(但常见的)结果。许多公司都有自己的变种:Sun Microsystems的SunOS、IBM的AIX、HP的HPUX(又名H-Pucks)以及SGI的IRIX。AT&T/贝尔实验室和这些其他厂商之间的法律纠纷给UNIX带来了阴影,许多人想知道它是否能够存活下来,尤其是Windows推出后并占领了大部分PC市场……

补充:然后出现了Linux 

幸运的是,对于UNIX来说,一位名叫Linus Torvalds的年轻芬兰黑客决定编写他自己的UNIX版本,该版本严重依赖最初系统背后的原则和思想,但没有借用原来的代码集,从而避免了合法性问题。他征集了世界各地许多其他人的帮助,不久,Linux就诞生了(同时也开启了现代开源软件运动)。

随着互联网时代的到来,大多数公司(如谷歌、亚马逊、Facebook和其他公司)选择运行Linux,因为它是免费的,可以随时修改以适应他们的需求。事实上,如果不存在这样一个系统,很难想象这些新公司的成功。随着智能手机成为占主导地位的面向用户的平台,出于许多相同的原因,Linux也在那里找到了用武之地(通过Android)。史蒂夫·乔布斯将他的基于UNIX的NeXTStep操作环境带到了苹果公司,从而使得UNIX在台式机上非常流行(尽管很多苹果技术用户可能都不知道这一事实)。因此,UNIX今天比以往任何时候都更加重要。如果你相信有计算之神,那么应该感谢这个美妙的结果。

标签: #c语言开发操作系统必读书籍