计算机系统:硬件与软件
欢迎学习计算机科学中最基础的章节之一!“硬件与软件”这一部分旨在为理解计算机的运作原理打下坚实基础。如果这些术语听起来有些抽象,别担心,我们将通过简单的例子来剖析计算机的物理部件是如何与让其发挥作用的指令进行交互的。
掌握这一主题至关重要,因为它能为你理解编程提供背景知识。你需要清楚当你运行程序时,计算机内部究竟发生了什么!
3.6.1 基础概念:硬件与软件
核心概念定义
每一个计算机系统都建立在两个基本要素的交互之上:硬件(Hardware)和软件(Software)。
1. 硬件
硬件是指计算机系统的电子组件。它是你可以触碰到的(或者能感受到它散发热量的!)物理实体。
- 例子: 处理器(CPU)、内存(RAM)、显示器、键盘以及连接它们的线缆。
核心要点: 硬件是执行指令的机械装置。
2. 软件
软件是指利用硬件执行的指令序列(程序)。
- 它是无形的——你无法触摸软件本身,只能触碰到存储它的存储设备。
- 软件是指挥中心;它告诉硬件具体执行什么任务以及何时执行。
关系: 没有软件,硬件毫无用处;而没有底层硬件架构,软件也无法运行。
3.6.2 软件深入:系统软件与应用软件
根据用途,软件通常被分为两大类。
1. 系统软件
系统软件旨在管理和控制计算机硬件,并为应用软件的运行提供平台。
- 它保证计算机顺畅运行。
- 类比: 如果你的计算机是一辆汽车,系统软件就是引擎和转向系统。
2. 应用软件
应用软件旨在为用户执行特定任务。
- 它是让用户能够高效工作或进行娱乐的软件。
- 例子: 文字处理器、网页浏览器、视频游戏、照片编辑工具。
关键系统软件组件的功能
a. 操作系统 (OS)
操作系统 (OS)(如 Windows、macOS 或 Linux)是最关键的系统软件。
操作系统的主要作用是向用户和其他软件屏蔽硬件的复杂性。当程序需要保存文件时,它会向操作系统发出请求,而不是直接操作硬盘驱动器。
操作系统通过以下几个关键功能来管理系统资源:
- 调度 (Scheduling): 决定处理器接下来应该运行哪些任务或进程,以及运行多长时间,确保所有运行中的程序都能公平地访问 CPU。
- 内存分配 (Memory Allocation): 管理主存(RAM)。当程序和数据加载时,操作系统会为其分配空间,并确保不同程序的内存空间互不干扰。
(注:你只需要了解主存是如何分配的,不需要学习虚拟内存。) - I/O 设备管理: 处理来自外设(打印机、鼠标、屏幕等)的输入和输出。它管理这些设备与系统其他部分之间的通信。
- 中断处理 (Interrupt Handling): 处理来自硬件或软件的突发优先信号(中断),例如按下一个键、打印机缺纸或计时器时间到。
中断处理步骤概念:
- 事件发生(例如点击鼠标)。
- 硬件向 CPU 发送中断信号。
- CPU 暂停当前正在执行的工作(取指-执行周期)。
- CPU 保存当前状态(易失性环境),以便之后可以恢复。
- CPU 识别中断类型并运行相应的中断服务例程 (ISR)。
- ISR 处理请求(例如处理鼠标点击)。
- 一旦 ISR 完成,CPU 恢复保存的环境并恢复执行原始任务。
b. 实用程序 (Utility Programs)
这些程序提供了额外的功能,以辅助计算机系统的管理。
- 例子: 病毒查杀程序(保护文件)或压缩程序(减小文件大小)。
c. 库 (Libraries)
库是预先编写好的、可复用的例程(子程序/代码)集合,程序员可以直接使用。它们节省了时间,因为程序员无需从头开始编写常用功能(如计算平方根或绘制图形)。
d. 翻译程序 (Translators)
这些程序将人类编写的代码转换为 CPU 可以执行的机器代码(下一节将详细介绍)。
快速回顾:系统软件功能
OS 作用: 屏蔽硬件复杂性,管理资源。
四大关键任务: 调度、内存、I/O、中断。
实用程序: 管理工具(如杀毒软件)。
库: 给程序员使用的可复用代码块。
3.6.3 编程语言与翻译软件
计算机只理解二进制(0 和 1),但人类编写代码所用的语言更易于阅读。翻译程序架起了这座桥梁。
3.6.3.1 编程语言的分类
编程语言根据其离硬件的距离进行广泛分类。
1. 低级语言(靠近硬件)
这些语言需要对处理器架构有深入的了解。
- 机器代码 (Machine Code): 这是最终的低级语言。
- 完全以二进制表示(0 和 1 的序列)。
- 由 CPU 直接执行。
- 用机器代码编写程序极其困难,且容易出错。
- 汇编语言 (Assembly Language): 使用助记符(短缩写)来表示机器代码指令。
- 例子: 你可能会写 ADD 或 JUMP,而不是编写二进制序列。
- 汇编指令与单条机器指令之间通常存在 1:1 的关系。
低级语言的优点:
- 用低级语言编写的程序运行速度极快。
- 它们非常节省内存(使用的资源最少)。
- 它们允许直接控制硬件,这对于操作系统或嵌入式系统至关重要。
低级语言的缺点:
- 它们编写、调试和维护非常困难。
- 它们不具有可移植性;为一种 CPU 编写的代码无法在另一种 CPU 上运行。
2. 高级语言(靠近用户)
这些语言类似于人类语言(英语、数学),并屏蔽了硬件的复杂性。
- 命令式高级语言: 一种语言(如 Python、Java、C#),程序员在其中提供一系列指令,描述执行任务所需的步骤(即,*如何*去做)。
- 它们更易于学习、调试,通常可以在不同硬件之间移植。
人们常使用“代”(如第二代、第三代语言)这一术语,但你只需要将其分类为低级语言(机器语言、汇编语言)和高级语言(命令式语言)即可。
3.6.3.2 程序翻译器的类型
由于 CPU 只理解机器代码,高级源代码必须进行翻译。这是由三种主要类型的软件完成的:
1. 汇编程序 (Assembler)
汇编程序将汇编语言翻译成机器代码(目标代码)。由于指令之间存在 1:1 的对应关系,这个过程非常直接。
2. 编译器 (Compiler)
编译器在程序运行之前,将整个程序(源代码)翻译成可执行文件(目标代码)。
- 过程: 源代码 -> 编译器 -> 目标代码(可执行文件) -> 运行。
- 速度: 一旦编译完成,程序运行速度非常快,因为所有翻译工作都是提前完成的。
- 调试: 编译后会一次性报告错误,这使得初步调试稍微困难一些。
- 源代码 vs. 目标代码: 源代码是人类可读的原始代码。目标代码是翻译程序生成的机器可读的二进制输出。
3. 解释器 (Interpreter)
解释器在程序运行的同时,逐行进行翻译和执行。
- 过程: 源代码 -> (解释器翻译并执行第 1 行) -> (翻译并执行第 2 行) -> ...
- 速度: 执行速度通常比编译代码慢,因为每次运行程序时都要重复进行翻译。
- 调试: 调试更容易,因为当某一行失败时,错误会立即报告。
何时使用哪种?(编译 vs. 解释)
- 编译适用于: 向公众发布的商业软件,此时速度和保护源代码是首要任务。
- 解释适用于: 开发和测试期间,或者可移植性至关重要的语言(如网页脚本)。
中间语言(字节码 Bytecode)
一些现代高级语言(如 Java)使用两步翻译过程,产生中间语言(通常称为字节码)。
- 为什么要使用中间语言?
- 可移植性: 中间代码不绑定于特定的处理器;它是机器无关的。
- 安全性: 在执行前,可以对中间代码进行安全性检查。
- 内存: 中间语言代码通常比完整的机器代码使用更少的内存。
- 如何使用:
- 虚拟机 (VM) 解释并执行中间代码。
- 或者,即时编译器 (JIT Compiler) 在执行前,将中间代码转换为适合当前运行环境的机器代码。
核心要点:翻译周期
高级代码需要翻译(编译器或解释器)才能运行。
低级汇编代码需要汇编程序。
中间代码提供了可移植性。