1、《深入理解计算机系统》--计算机系统介绍

1.1信息就是位+上下文

核心观点:信息就是位 + 上下文

这是本节的核心思想。系统中的所有信息(文件、程序、数据、网络传输)本质上都是一串比特(0 和 1)。

  • 区分依据: 我们之所以能区分不同的数据(如整数、浮点数、字符串),完全取决于读取这些数据的上下文

2. hello.c 源程序的表示

  • 源文件本质: hello.c 是一个文本文件,由程序员通过编辑器创建。

  • 字节序列: 源代码在计算机中存储为字节序列。8 个位(比特)组成一个字节。

  • ASCII 编码: 大部分现代计算机使用 ASCII 标准来表示文本字符,即用一个唯一的单字节整数值表示每个字符。

ASCII 码示例分析

书中通过 hello.c 的 ASCII 文本表示(图 1-2)进行了详细说明:

  • 字符与数值对应: 例如字符 # 对应整数值 35,字符 i 对应 105。

  • 不可见字符: 每个文本行的末尾都有一个看不见的换行符 \n,其对应的整数值为 10。

  • 文件分类: 只由 ASCII 字符构成的文件称为文本文件 ,其他文件则称为二进制文件

程序员需要关注的点

  • 数字的机器表示: 程序员需要了解数字在机器中的表示方式,因为机器中的表示是实际数值的有限近似值,这有时会导致意想不到的行为(例如浮点数精度问题)。

  • 后续内容: 关于数字机器表示的基本原理将在第 2 章详细描述。

1.2 程序被其他程序翻译成不同的格式

核心流程:程序的生命周期

程序的生命周期始于人类可读的高级语言(如 C 语言),最终转化为机器可执行的二进制指令。在 Unix/Linux 系统中,这个过程通常通过 GCC 编译器驱动程序完成,命令格式为 gcc -o hello hello.c

整个翻译过程由编译系统完成,分为四个关键阶段:

预处理阶段 (Preprocessing)
  • 执行者: 预处理器 (cpp)

  • 作用: 处理源文件中以 # 开头的命令。

  • 示例: 比如 #include <stdio.h> 命令,预处理器会读取系统头文件 stdio.h 的内容,并将其直接插入到源程序中。

  • 输出: 得到一个经过修改的源程序,通常以 .i 为扩展名(如 hello.i)。

编译阶段 (Compilation)
  • 执行者: 编译器 (ccl)

  • 作用: 将预处理后的文本文件(hello.i)翻译成汇编语言程序。

  • 输出: 得到一个文本文件,通常以 .s 为扩展名(如 hello.s)。这个文件包含了函数(如 main)的定义,每行语句对应一条低级的机器指令描述(如 subq, movl, call 等)。

汇编阶段 (Assembly)
  • 执行者: 汇编器 (as)

  • 作用: 将汇编语言程序(hello.s)翻译成机器语言指令。

  • 输出: 将指令打包成一种称为可重定位目标程序的格式,保存在目标文件中,通常以 .o 为扩展名(如 hello.o)。这是一个二进制文件,如果直接打开会看到乱码。

链接阶段 (Linking)
  • 执行者: 链接器 (ld)

  • 作用: 合并程序中调用的其他代码。例如 hello 程序调用了标准库中的 printf 函数,链接器会将包含 printf 函数的预编译目标文件(如 printf.o)合并到 hello.o 中。

  • 输出: 得到最终的可执行目标文件(如 hello),它可以被加载到内存中,由系统执行。

关键概念总结

  • 编译系统:由预处理器、编译器、汇编器和链接器共同构成。

  • 文件格式演变:源程序(文本) →→ 修改的源程序(文本) →→ 汇编程序(文本) →→ 可重定位目标程序(二进制) →→ 可执行目标程序(二进制)。

  • 汇编语言:作为中间层,为不同高级语言的编译器提供了通用的输出语言。

为什么程序员需要理解编译系统

  • 优化程序性能 (Optimize Performance)

  • 理解链接时的错误 (Understand Linking Errors)

  • 避免安全漏洞 (Avoid Security Vulnerabilities)

1.3 Unix系统中,如何通过shell(命令解释器)运行一个名为hello的可执行文件,以及shell在其中的作用

  1. 背景:C 语言源程序(hello.c)已经通过编译系统被翻译成了可执行的目标文件(hello),并存储在磁盘上。

  2. 运行过程:

    1. 用户在 Unix 系统的 shell 中输入命令 ./hello 来启动该程序。

    2. shell 作为命令行解释器,接收到命令后,会判断该命令是否为内置命令。

    3. 由于 ./hello 不是内置命令,shell 会将其识别为可执行文件名,并负责加载和运行该文件。

  3. 执行结果:

    1. hello 程序开始运行,在屏幕上输出 "hello, world" 的消息。

    2. 程序执行完毕后终止。

    3. shell 重新获得控制权,输出提示符,等待用户输入下一条命令。

1.4 系统的硬件组成

系统硬件的四大核心组成部分

为了理解程序如何运行,我们需要了解一个典型系统(如 Intel 系统)的硬件组织结构。

1.1 总线
  • 定义:贯穿整个系统的一组电子管道,称为总线。

  • 功能:携带信息字节,并在各个硬件部件之间传递数据。

  • 特性:通常传送定长的字节块(即"字")。现代机器的字长通常为 4 字节(32位)或 8 字节(64位)。

1.2 I/O 设备
  • 定义:输入/输出设备,是系统与外部世界的联系通道。

  • 组成:包括键盘、鼠标(输入)、显示器(输出)以及磁盘驱动器(长期存储)。

  • 连接方式:通过控制器或适配器连接到 I/O 总线。它们的功能是在 I/O 总线和具体的 I/O 设备之间传递信息。

  • 初始状态:可执行程序(如 hello)最初是存放在磁盘上的。

1.3 主存
  • 定义:一个临时存储设备(物理上由 DRAM 芯片组成)。

  • 功能:在处理器执行程序时,用来存放程序和程序处理的数据。

  • 逻辑结构:可以看作一个线性的字节数组,每个字节都有唯一的从零开始的地址。

1.4 处理器
  • 定义:中央处理单元,是解释(或执行)存储在主存中指令的引擎。

  • 核心组件:

    • 程序计数器:一个存储设备(寄存器),始终指向主存中某条机器语言指令的地址。

    • 寄存器文件:一个小型的存储设备,由一些单个字长的寄存器组成。

    • 算术/逻辑单元:计算新的数据和地址值。

处理器的工作流程与操作类型

处理器的工作原理是基于指令集架构的简单模型:

  • 执行循环:处理器不断执行 PC 指向的指令,然后更新 PC 指向下一指令(除非遇到跳转指令)。

  • 基本操作:CPU 执行指令时主要进行以下四类简单操作:

    • 加载:从主存复制数据到寄存器。

    • 存储:从寄存器复制数据到主存。

    • 操作:将两个寄存器的内容复制到 ALU 进行运算,结果存回寄存器。

    • 跳转:从指令本身抽取数据,覆盖 PC 的值,改变指令执行的顺序。

总结图示

图 1-4 展示了典型系统的硬件组成:

  • CPU 通过 系统总线 连接到 I/O 桥。

  • I/O 桥 分别连接 内存总线(通向主存)和 I/O 总线。

  • I/O 总线 连接各种控制器(如 USB 控制器、磁盘控制器、图形适配器),进而连接到具体的 I/O 设备(键盘、鼠标、显示器、磁盘)。

  • 关键点:hello 可执行文件最初存储在磁盘上,需要经过 I/O 子系统加载到主存,才能被 CPU 执行。

1.5 运行hello程序

这段内容通过三个步骤,详细拆解了在 Unix 系统中运行 ./hello 命令时,计算机硬件系统内部发生的数据流动过程

接收用户输入 (图 1-5)

当用户在键盘上输入 ./hello 并敲击回车键时:

  • 触发机制:Shell 程序检测到命令输入结束。

  • 数据路径:键盘产生的电信号经由 USB 控制器 和 I/O 总线,通过 I/O 桥 转换,最终经由 内存总线 将字符串数据写入 主存储器。

  • 结果:Shell 程序获取了用户输入的命令字符串。

加载可执行文件 (图 1-6)

Shell 程序解析命令后,开始加载磁盘上的 hello 可执行文件:

  • 数据源:存储在 磁盘 上的 hello 可执行文件(包含代码和数据,如 "hello, world\n")。

  • 传输技术:利用 直接存储器存取 技术,数据不经过处理器,直接从磁盘经由 磁盘控制器、I/O 总线 和 I/O 桥,通过 内存总线 传输到 主存储器。

  • 结果:hello 程序的机器码和所需数据被完整加载到内存中,准备执行。

执行程序与输出 (图 1-7)

处理器开始执行 hello 程序的指令:

  • 执行过程:处理器从内存中读取指令,将字符串 "hello, world\n" 从 主存储器 复制到处理器的 寄存器文件,再写回到内存(或直接通过总线)。

  • 显示输出:数据经由 I/O 桥 和 I/O 总线 传输到 图形适配器,最终显示在 显示器 上。

  • 结果:用户在屏幕上看到 "hello, world" 的输出。


总结

整个过程展示了计算机系统中"输入 -> 处理 -> 输出"的基本工作流,核心在于数据在 CPU、主存、磁盘 和 I/O 设备 之间通过 总线系统 的高效流动。

1.6 高速缓存

核心问题:存储器的速度与容量矛盾

  • 性能瓶颈:计算机系统中存在大量的数据复制操作(如从磁盘到内存,从内存到CPU),这些复制操作是系统运行的"开销",会减慢程序的执行速度。

  • 速度差异:

    • 磁盘 vs 内存:磁盘容量大但极慢,从磁盘读取数据的开销比从主存读取大数百万倍。

    • 内存 vs 寄存器:主存容量大但比寄存器慢,从寄存器读取数据比从主存读取快约100倍。

  • 趋势:随着技术发展,处理器速度的提升远快于主存速度的提升,两者之间的速度差距在持续增大。

解决方案:高速缓存存储器

为了解决CPU与主存之间的速度差异,系统设计者引入了高速缓存(Cache):

  • 定义:高速缓存是更小、更快的存储设备,作为处理器和主存之间的临时集结区域,存放处理器近期可能会需要的信息。

  • 层级结构:

    • L1 高速缓存:位于处理器芯片上,容量较小(数万字节),访问速度几乎与寄存器一样快。

    • L2 高速缓存:容量更大(数十万到数百万字节),通过特殊总线连接到处理器,访问时间比L1稍长,但比访问主存快5~10倍。

    • L3 高速缓存:较新的强大系统可能还包含L3缓存。

工作原理:局部性原理

  • 原理:程序具有访问局部区域数据和代码的趋势(即"局部性")。

  • 效果:通过在高速缓存中存放可能经常访问的数据,大部分内存操作都能在快速的高速缓存中完成,从而极大提升系统性能。

重要结论

  • 性能提升:意识到高速缓存存在的应用程序员,能够利用高速缓存将程序性能提高一个数量级。

  • 硬件示意图:图1-8展示了高速缓存位于CPU芯片内部,介于寄存器文件和系统总线之间,作为CPU与主存通信的快速中转站。

简而言之,高速缓存通过利用程序的局部性原理,填补了CPU与主存之间的速度鸿沟,是现代计算机系统性能优化的关键。

1.7 存储设备形成层次结构

存储器层次结构的概念

计算机系统中的存储设备被组织成一个金字塔形的层次结构(如图 1-9 所示)。在这个结构中:

  • 从上到下:设备的访问速度越来越慢,容量越来越大,每字节的造价也越来越便宜。

  • 从下到上:设备的速度更快,容量更小,造价更贵。

层次结构的具体层级

图 1-9 展示了一个典型的 7 层存储器层次结构:

  • L0 (第 0 层):寄存器。位于 CPU 内部,速度最快,容量最小。

  • L1 - L3 (第 1-3 层):高速缓存。分为 L1、L2、L3 三级。通常 L1 速度最快、最小;L3 相对较慢、较大。它们主要由 SRAM(静态随机存取存储器)构成。

  • L4 (第 4 层):主存。由 DRAM(动态随机存取存储器)构成,容量比缓存大得多,但速度比缓存慢。

  • L5 (第 5 层):本地二级存储。通常是本地磁盘(如 SSD 或 HDD),容量巨大,速度比主存慢很多。

  • L6 (第 6 层):远程二级存储。如分布式文件系统或 Web 服务器,通过网络访问,速度最慢,容量理论上无限。

层次结构的核心思想

存储器层次结构的核心思想是:上一层的存储器作为下一层存储器的高速缓存。

  • 寄存器文件是 L1 高速缓存的缓存。

  • L1 高速缓存是 L2 高速缓存的缓存。

  • L2 高速缓存是 L3 高速缓存的缓存。

  • L3 高速缓存是主存的缓存。

  • 主存是本地磁盘的缓存。

  • 本地磁盘是远程网络存储的缓存。

这种结构使得 CPU 能够以接近寄存器的速度访问数据,同时拥有接近磁盘的巨大存储容量。

对程序员的意义

程序员可以通过理解存储器层次结构来优化程序性能。例如,编写具有良好局部性的代码,可以最大限度地利用高速缓存,减少访问慢速存储器的次数,从而显著提升程序运行速度。

1.8 操作系统管理硬件

操作系统的核心作用:管理硬件与提供抽象

操作系统(OS)是位于应用程序和硬件之间的一层软件,其主要目的是管理硬件资源并为应用程序提供一个统一、安全的运行环境。

  • 管理角色:应用程序(如 shell 和 hello 程序)不直接访问键盘、显示器、磁盘或主存,而是通过操作系统提供的服务来间接操作硬件。

  • 两大基本功能:

    • 防止失控:防止失控的应用程序滥用硬件资源。

    • 提供统一接口:向应用程序提供简单一致的机制,来控制复杂且各不相同的底层硬件设备。

操作系统提供的三大抽象概念

为了实现上述功能,操作系统通过三个基本抽象概念来管理硬件资源:

  • 文件(File):是对 I/O 设备(如磁盘)的抽象表示。

  • 虚拟内存(Virtual Memory):是对主存和磁盘 I/O 设备的抽象表示。

  • 进程(Process):是对处理器、主存和 I/O 设备的抽象表示。

这两张图片详细解释了计算机科学中"进程(Process)"这一核心概念,以及操作系统是如何通过"上下文切换(Context Switching)"来管理和调度进程的。

进程的本质:一种"假象"

进程是操作系统对一个正在运行的程序的抽象。

  • 独占假象:当一个程序(如 hello)在系统上运行时,操作系统会制造一种假象,让该程序感觉它独占了处理器、主存和 I/O 设备。它看起来像是在不间断地执行指令。

  • 并发运行:在现代系统中,可以同时运行多个进程。实际上,这些进程的指令是交错执行的(即并发)。即使在单核 CPU 上,操作系统也能通过快速切换进程,让它们看起来像是在同时运行。

核心机制:上下文切换

为了实现进程的并发,操作系统使用了一种称为上下文切换的机制。

  • 什么是上下文:上下文是指操作系统为了跟踪进程运行所需的所有状态信息,包括程序计数器(PC)、寄存器文件的当前值以及主存的内容。

  • 切换过程:当操作系统决定将控制权从当前进程转移到另一个新进程时,它会执行以下步骤:

    • 保存:保存当前进程的上下文。

    • 恢复:恢复新进程的上下文。

    • 传递控制权:将控制权交给新进程。

  • 结果:新进程会从它上次停止的地方继续执行。

具体案例:Shell 与 Hello 程序

文中以运行 hello 程序为例,展示了进程的切换流程:

  1. 初始状态:只有 shell 进程在运行,等待命令行输入。

  2. 执行请求:用户输入 ./helloshell 通过系统调用请求操作系统执行 hello 程序。

  3. 切换与创建:操作系统保存 shell 进程的上下文,创建一个新的 hello 进程及其上下文,并将控制权交给 hello

  4. 恢复:hello 进程终止后,操作系统恢复 shell 进程的上下文,shell 继续等待下一个命令。

系统内核的作用

  • 管理者:从一个进程到另一个进程的转换是由操作系统内核(Kernel)管理的。

  • 内核特性:内核是操作系统代码常驻主存的部分,它不是一个独立的进程,而是管理系统中所有进程所用代码和数据结构的集合。

  • 系统调用:当应用程序(如 hello)需要进行读写文件等操作时,会执行系统调用指令,将控制权传递给内核,由内核执行相关操作并返回结果。

总结

进程是操作系统提供的一种抽象,它让每个程序都感觉自己独占了硬件资源。而操作系统通过上下文切换这一机制,在多个进程间快速切换,实现了并发运行的效果。这一过程由内核负责管理,通过系统调用来实现应用程序与操作系统的交互。

线程 (Thread)

  • 定义:线程是进程内的执行单元。一个进程可以包含多个线程。

  • 特点:

    • 同一进程内的所有线程共享相同的代码和全局数据。

    • 线程比进程更轻量级,线程间的切换开销通常比进程间切换要小。

    • 线程非常适合多处理器环境,能充分利用多核CPU的性能。

  • 应用:在网络服务器等需要并行处理的场景中,线程是一种重要的编程模型。

虚拟内存 (Virtual Memory)

  • 核心概念:虚拟内存是操作系统提供的一种抽象,它给每个进程一种"独占主存"的假象。每个进程看到的内存视图都是一致的,这个视图被称为"虚拟地址空间"。

  • 工作原理:虚拟内存将进程的内存内容存储在磁盘上,并利用主存作为磁盘的高速缓存,从而扩展了可用内存的容量。

Linux 进程的虚拟地址空间布局

图1-13展示了Linux进程虚拟地址空间的典型结构(从低地址到高地址):

  • 程序代码和数据:位于地址空间的底部。包括只读的代码段(如hello程序的指令)和已初始化的全局变量数据段。

  • 堆 (Heap):位于代码和数据段之上。用于动态内存分配(如C语言中的mallocfree函数),运行时可动态扩展或收缩。

  • 共享库 (Shared Libraries):位于地址空间的中间部分。用于存放C标准库、数学库等共享库的代码和数据。

  • 栈 (Stack):位于地址空间的顶部。用于实现函数调用,保存局部变量和返回地址。每次函数调用时栈增长,函数返回时栈收缩。

  • 内核虚拟内存:位于地址空间的最顶部,用户代码不可见。这是操作系统内核保留的区域,应用程序不能直接读写,必须通过系统调用让内核代为执行操作。

总的来说,虚拟内存通过地址空间的抽象,将复杂的物理内存管理对应用程序隐藏起来,使得程序开发和运行更加简单和安全。

这张图片主要介绍了操作系统中"文件(File)"这一概念及其重要性,特别是从 Unix 系统的角度进行了解释。

文件的定义

  • 基本概念:文件被定义为字节序列。

  • 广义理解:不仅仅是磁盘上的数据,系统中的所有输入/输出设备(包括磁盘、键盘、显示器,甚至网络)都可以被看作是文件。

  • 文件概念的重要性

  • 统一视图:文件概念的强大之处在于它为应用程序提供了一个统一的视图来处理系统中各种各样的 I/O 设备。

  • 简化开发:程序员无需了解具体硬件(如特定磁盘技术)的底层细节。例如,处理磁盘文件内容的程序员不需要知道磁盘的物理结构。

  • 可移植性:同一个程序可以在使用不同磁盘技术的不同系统上运行,因为它们都通过统一的文件接口进行交互。

  • 实现方式

  • Unix I/O:系统中的所有输入输出操作都是通过调用一组称为 Unix I/O 的系统函数(如读写文件)来实现的。

总结

文件作为字节序列的抽象,极大地简化了应用程序对硬件设备的访问,使得程序开发更加便捷且具有良好的可移植性。

1.9 系统之间利用网络通信

网络作为 I/O 设备

  • 核心概念:网络在计算机系统中被视为一种 I/O(输入/输出)设备,与键盘、磁盘、显示器等地位相同。

  • 工作原理:当系统从主存复制数据到网络适配器(网卡)时,数据流会经过网络传输到另一台机器,而不是传输到本地磁盘。反之,系统也可以从网络接收数据并复制到主存。

  • 重要性:随着 Internet 的普及,跨主机传输信息已成为计算机系统最重要的功能之一。电子邮件、即时通信、万维网、FTP 和 Telnet 等应用都是基于此功能。

远程执行示例:通过 Telnet 运行 Hello 程序

文中以经典的 Telnet 协议为例,展示了客户端-服务器模式下的交互流程:

  1. 用户输入:用户在本地键盘输入 hello 命令。

  2. 发送请求:本地 Telnet 客户端将命令字符串发送给远程 Telnet 服务器。

  3. 远程执行:远程服务器将命令传递给其 Shell,Shell 运行 hello 程序,并将输出结果发送回 Telnet 服务器。

  4. 结果回传:远程 Telnet 服务器将输出字符串(如 "hello world\n")发送回本地客户端。

  5. 本地显示:客户端在本地显示器上打印输出结果。

客户端-服务器交互模型

  • 典型模式:这种"请求-响应"的交互模式是所有网络应用的基础。

  • 学习展望:后续章节(第 11 章)将深入讲解如何构建网络应用程序,并利用这些知识创建一个简单的 Web 服务器。

总结

网络通信的本质是数据的复制,只不过数据的源头和目的地跨越了不同的物理主机。通过将网络抽象为 I/O 设备,操作系统能够以统一的方式处理本地和远程的数据传输。

1.10 并发与并行

并发与并行的区别

  • 并发 (Concurrency):指一个系统同时具有多个活动(例如多个程序或线程在运行)。在早期的单处理器系统中,这是通过操作系统在多个任务间快速切换(上下文切换)来"模拟"出来的,给人一种同时运行的假象。

  • 并行 (Parallelism):指利用并发来让系统实际运行得更快。并行通常需要硬件上的支持(如多核处理器),能够真正地同时执行多个任务。

三个层次的并行技术

文中从高到低介绍了三种主要的并行方式:

线程级并发 (Thread-Level Concurrency)

这是最高层次的并行,依赖于多处理器硬件。

  • 多核处理器 (Multicore):将多个 CPU 核心集成在一块芯片上(如图 1-17 所示的 4 核结构),每个核心都有自己的 L1/L2 缓存,共享 L3 缓存和主存。

  • 超线程 (Hyperthreading):一种让单个物理核心看起来像多个核心的技术。它通过复制 CPU 的部分硬件(如寄存器),使得一个核心可以同时处理多个线程,从而提高资源利用率(例如 4 核 i7 处理器可处理 8 个线程)。

  • 优势:多处理器系统减少了模拟并发的开销,使程序运行得更快,但也要求程序员编写多线程代码来充分利用硬件。

指令级并行 (Instruction-Level Parallelism)

这是较低层次的并行,由处理器硬件自动完成。

  • 流水线 (Pipelining):将执行一条指令的过程划分为多个阶段(如取指、译码、执行),这些阶段可以并行处理不同的指令,从而实现接近一个时钟周期执行一条指令的速率。

  • 超标量 (Superscalar):现代处理器可以同时发射(issue)多条指令,即在一个时钟周期内执行多条指令。这要求程序员编写代码时考虑指令间的依赖关系,以获得更高性能。

单指令、多数据并行 (SIMD)

这是最低层次的并行,主要针对特定类型的计算。

  • 概念:允许一条指令同时操作多个数据元素(例如,一条指令同时对 8 对浮点数进行加法运算)。

  • 应用:主要用于提高图像、声音和视频处理等数据密集型应用的执行速度。

  • 实现:通常通过编译器支持的特殊向量数据类型(如 GCC 的向量扩展)来编写程序。

总结

现代计算机性能的提升不再仅仅依赖于提高时钟频率,而是更多地依赖于并行化。从操作系统层面的多线程,到处理器硬件层面的流水线、超标量和 SIMD 技术,计算机系统在不同层次上同时利用多个计算资源来完成任务。

多核处理器 (Multicore) 既可以实现并发,也可以实现并行,但它的核心价值在于实现真正的并行。

为了理解这一点,我们需要区分这两个概念:

并行 (Parallelism) ------ 多核的核心能力

这是多核处理器最本质的特性。

  • 定义 :多个任务同时在物理上执行。

  • 多核的作用:因为一块芯片上有多个物理核心(比如 4 个、8 个甚至更多),操作系统可以将不同的线程或进程直接分配给不同的核心。

  • 结果 :这些核心可以同时计算,互不干扰。例如,一个核心在处理视频渲染,另一个核心在处理网页加载,这是真正的并行。

并发 (Concurrency) ------ 多核可以更好地支持它

  • 定义 :多个任务在逻辑上看起来是同时进行的(即使物理上是轮流执行的)。

  • 单核 vs 多核

    • 单核CPU上,并发是通过操作系统快速切换任务来实现的(看起来像同时进行,实际上是轮流跑)。

    • 多核CPU上,并发不仅可以通过切换实现,更可以通过真正的并行来实现。

  • 结果:多核处理器极大地提升了并发任务的执行效率。

总结

多核处理器提供了物理基础 ,使得操作系统能够将并发的任务真正转化为并行的执行,从而显著提升系统性能。

1.11计算机系统中抽象的重要性

什么是抽象?

  • 核心定义:抽象是隐藏实际实现的复杂性,只暴露简单的接口。

  • 生活类比:就像使用微波炉,你只需要知道按哪个按钮加热多久,而不需要懂内部的电路原理。在编程中,API(应用程序接口)就是一个典型的抽象,程序员调用函数时不需要知道函数内部的具体代码。

计算机系统中的抽象层次

图片中的图 1-18展示了计算机系统是如何通过层层抽象构建起来的。从下往上,每一层都为上一层提供服务,并隐藏了下一层的复杂性。

  • 最底层(硬件层):

    • 操作系统 (OS)、处理器 (CPU)、主存 (Memory)、I/O 设备:这是物理存在的硬件和基础软件。
  • 第一层抽象(对硬件的抽象):

    • 指令集架构 (ISA):它是对处理器的抽象。程序员(或编译器)写机器码时,不需要知道 CPU 内部是用什么电路实现的,只需要遵循指令集规范即可。

    • 虚拟内存 (Virtual Memory):它是对主存的抽象。程序运行时感觉自己独占了整个内存空间,不需要关心物理内存是否被其他程序占用或是否需要换入换出硬盘。

    • 文件 (File):它是对I/O 设备的抽象。无论底层是硬盘、U盘还是网络存储,对用户和程序来说,它们都统一表现为"文件",通过读写文件来操作。

  • 第二层抽象(对执行过程的抽象):

    • 进程 (Process):它是对正在运行的程序的抽象。操作系统把一个运行中的程序包装成一个"进程",赋予它独立的资源和状态,使得多个程序可以并发运行而不互相干扰。
  • 最顶层抽象(全系统抽象):

    • 虚拟机 (Virtual Machine):这是最高级的抽象,它模拟了整个计算机系统(包括硬件和操作系统)。你可以在一台物理电脑上运行多个不同的操作系统(如 Windows、Linux、MacOS),每个操作系统都运行在自己的虚拟机里,互不干扰。

抽象的重要性

  • 简化复杂性:如果没有抽象,程序员需要直接操作复杂的硬件电路,软件开发将变得极其困难。

  • 提高可移植性:因为有了指令集架构和虚拟机的抽象,软件可以在不同的硬件上运行,只要它们遵循相同的抽象规范(例如,Java 程序可以在任何安装了 JVM 的机器上运行)。

  • 提高安全性与稳定性:虚拟内存和进程的抽象可以防止一个程序的崩溃影响到整个系统或其他程序。

总结:

这张图揭示了计算机科学的核心思想------分层抽象。通过将复杂的系统拆解成一层层简单的接口,计算机系统才能变得既强大又易于使用。

相关推荐
时代的凡人5 小时前
0208晨间笔记
笔记
小白同学_C5 小时前
Lab4-Lab: traps && MIT6.1810操作系统工程【持续更新】 _
linux·c/c++·操作系统os
testpassportcn6 小时前
AWS DOP-C02 認證完整解析|AWS DevOps Engineer Professional 考試
网络·学习·改行学it
不做无法实现的梦~7 小时前
ros2实现路径规划---nav2部分
linux·stm32·嵌入式硬件·机器人·自动驾驶
默|笙9 小时前
【Linux】fd_重定向本质
linux·运维·服务器
游乐码9 小时前
c#变长关键字和参数默认值
学习·c#
陈苏同学9 小时前
[已解决] Solving environment: failed with repodata from current_repodata.json (python其实已经被AutoDL装好了!)
linux·python·conda
“αβ”9 小时前
网络层协议 -- ICMP协议
linux·服务器·网络·网络协议·icmp·traceroute·ping
若风的雨9 小时前
【deepseek】RT-Thread 对 PCIe 的支持情况
系统架构