抽象是一种思维结构,它组织思维,以加快可靠计算的设计和构建,经常被认为是计算思维的基本原则。3.我们遗憾的是,面向K-12年级的计算机专业课程针对的是初学者,却很少暗示计算机专业人员在工作中使用的抽象概念。当2021年图灵奖庆祝Alfred Aho和Jeff Ullman设计的编程语言和编译器抽象时,向揭示更多高级抽象的方向迈出了一步。1在本专栏中,我将继续介绍一些抽象的例子,这些抽象是为操作系统发明的,并扩展到计算的其他领域。
计算机专业人士发明了这些高级的“系统抽象”来处理对于单独的程序员来说太大的大型系统。我先从操作系统的一些重要问题开始。
也许操作系统中最基本的抽象是“进程”,意思是正在执行的程序。这个想法是为了解决早期操作系统的可靠性问题而发明的。
1960年至1965年间,操作系统设计者着手构建计算机实用程序——强大的计算系统,将计算能力廉价地分布在大型用户网络中。这些系统旨在集成时间共享、虚拟内存、输入-输出流、共享文件系统、目录系统和编程支持接口方面的大量新发明。这些发明最大化了信息共享,最小化了开发时间,并将昂贵的CPU和内存资源的成本分摊到许多用户身上。
大约在1960年,大型程序的主要抽象是“模块和接口”。它要求将复杂的系统分解成简单的模块,通过它们的接口交换信息。例如,操作系统可以用作业和CPU调度、内存管理、输入输出、文件、目录和编程接口支持等模块来组织。不幸的是,这种方法没有奏效。无论设计人员如何仔细地指定模块功能和接口,当模块连接在一起并承受用户工作负载时,系统总是会崩溃。调试极其困难。
问题是,模块是一种控制结构,用于指导CPU一次完成一个任务。然而,操作系统必须为许多用户管理许多计算。没有简单的方法来可视化许多用户同时通过模块及其接口的工作。大系统不仅仅是拥有更多用户的小系统;多个用户在实现私有内存、共享文件和内存以及争夺有限的CPU、设备和内存资源时创建了新的动态。这些动态包括竞争条件、死锁、繁忙等待、数据在内存级别之间循环、对文件的访问、用户通过创建新的自治服务来扩展系统,以及预测吞吐量和响应时间。需要一种新的思维方式。这种新的思想被称为并发控制。
1964年出现的流程抽象为其他问题提供了优雅的解决方案。进程不仅仅是一个正在执行的程序。它是一个自主代理,根据请求为其他流程执行服务。进程是需要CPU时间和内存空间、与其他进程同步、创建和访问文件、搜索目录、响应事件以及与其他进程啮合以形成动态计算结构的实体。
进程的思想衍生出另一个重要的抽象概念——非终止计算。服务流程被设计成无限循环。在完成请求后,服务流程将返回到“归位”并等待下一个传入请求。隐藏在后台的守护进程执行有益的管理功能,如内存回收或将修改过的内存内容写回磁盘。设计师们学会了用持续运行的计算系统来思考问题。到20世纪60年代末,大多数操作系统设计师将操作系统视为一个合作的社会,其中大部分是不终止的进程,而不是堆积如山的模块。今天,您的笔记本电脑的活动监视器通常会显示您的操作系统正在运行200到500个进程。
相比之下,目前大多数编程课程只教授独立的终止程序:那些从输入开始,到输出结束的程序。在这个上下文中,一个非终止程序看起来像一个错误——无限循环。
系统抽象对于构建具有大量进程、用户、设备和网络连接的大型复杂系统至关重要。每个主要的计算系统领域都有自己的特征抽象。2例如,Internet有用于寻址主机的IP协议、用于克服噪声传输的TCP协议、域名命名、url、Web页面、标记语言等等。云具有通用的无限名称空间、不可伪造的指向存储文件的指针、数据中心、防止数据丢失的冗余等等。数据库系统有记录、字段、表、投影、连接、查询、原子事务、持久存储、文件向存储的永久承诺等等。这样的例子不胜枚举。
进程不仅仅是一个正在执行的程序。
计算系统复杂性的一个主要来源是大量的数字对象。系统抽象以两种方式简化了这种复杂性。首先,他们将所有同类对象合并到一个类中,并为所有对象设计一个管理器。管理器为允许进程在这些对象上执行的操作提供了一个接口。其次,类管理器为对象分配唯一的名称,并验证每一次访问以获得授权。必须保护包含这些名称和访问代码的指针不被更改。侧栏“文件的抽象说明了文件管理器的这些思想。
在操作系统和云存储中,对指向对象的不可更改指针的需求通过一种称为“能力”的较低级抽象得到满足。能力是一个位包,由(类型、访问、句柄)字段组成。type字段表示对象的类型。access字段是一个多位代码,指定可以对该对象执行类操作的哪个子集。句柄字段是对象的唯一代码,它将对象与其他所有相同类型的对象区别开来。
只要功能保留在内核空间中,它们就会受到保护,因为没有任何用户进程可以更改内核空间中的任何内容。当它们被传递到外部时,它们被一个加密校验和增强,使接收者能够验证它们自创建以来没有被更改。
能力在1966年被引入,并成为实现面向对象编程语言的原则。4它们被用于一些云存储系统,如TAHOE-LAS,以保证文件的私密性。
一类对象的系统抽象可以被描述为“抽象机器”,它的指令集是在接口上提供的操作,它隐藏的内部数据结构跟踪所有对象。文件管理器就是一个例子。
在操作系统和网络中,我们可以将抽象堆叠成一系列的层次。每个级别都可以由较低级别定义的抽象组成,但不能使用有关较高级别抽象的任何信息。
这种分层的第一个工作例子是多程序设计系统,由Edsger Dijkstra于1965年设计。5这个想法已经扩展到现代操作系统。典型的渲染是:
1-5级是微内核;它们以内核模式运行,可以访问所有内存。级别6-10是用户内核;它们以用户模式运行,只能访问调用它们的进程的私有内存。每一层都是一个抽象机器,它管理该层的对象类。
第10级是内核之外的用户服务集合,如图形用户界面、应用程序库(app)和性能分析工具。每个用户服务都有自己的系统抽象。
对象和操作可以由低级对象和操作组成。实际上,一个层次的抽象机器被嵌套在抽象机器内部,用于上一个层次。抽象机器的用户界面由所有嵌套机器的接口的联合组成。这种嵌套对高层隐藏了较低级别的细节。
在这一堆层次中,程序员必须设计成只向下调用而不向上调用。这可以防止循环等待(死锁)和自引用代码循环,并允许系统一次验证和测试一个级别。6这种限制要求重新定位思维。例如,考虑一个文件管理器程序员想要使用一个文件作为目录的容器。这似乎需要从文件管理器(级别6)向上调用目录管理器(级别7),请求创建一个文件管理器可以填充的目录。为了避免向上调用,我们将创建目录和填充文件的职责转移到shell(级别9)。shell可以向下调用级别7来创建目录,然后调用级别6来将文件加载到目录中。这种思维的重新定位简化了代码,并消除了任何与循环有关的问题。
分层系统抽象有一个意想不到的回报。许多设计师反对Dijkstra的提议,担心它过于简化、过于约束、失去功能。约束会引入复杂性来绕过它们。事情不是这样的。毫无疑问,分层系统会导致更小的内核。较小的内核速度更快,更容易测试和验证。多年来,唯一被证明是安全的操作系统被分层结构。现代的Sel4内核就是最新的例子。它体积小,结构紧凑,适合于物联网设备有限的记忆。
计算机的许多惊人进步都是由设计师创造和使用系统抽象实现的。这里概述的操作系统抽象只是用于组织大型系统的一些系统抽象。令人遗憾的是,在提供给新人的CT课程中,很少有关于大型程序和编译器的抽象,也没有关于系统抽象的讨论。如果没有这些高级的抽象概念,CT对于专业人士来说是毫无意义的。
抽象、系统或其他方式是否完全描述了计算?我认为不是。计算是对自然和人工信息处理过程的研究。系统抽象是我们用于设计和研究大规模、复杂信息过程的众多工具之一。
1.Aho, A.和Ullman, J. Abstractions,他们的算法和编译器。Commun。ACM 65, 2(2022年2月),76-91。
2.丹宁,pj和马泰尔,C。伟大的计算原理。麻省理工学院出版社,2015年。
3.丹宁,P.J.和泰德,M。计算思维。麻省理工学院出版社,2019年。
4.多程序计算的程序语义。Commun。ACM 9, 3(1966年3月),143-155。
5.“The”多程序设计系统的结构。Commun。ACM 11, 5(1968年5月),341-346。
6.Habermann, N., Flon, L.和cooper, L.操作系统家族中的模块化和层次结构。Commun。ACM 19, 5(1976年5月),266-272。
数字图书馆是由计算机协会出版的。版权所有©2022 ACM股份有限公司
没有发现记录