第一章 温故而知新

开始之前,回顾一下带我们进入编程世界的那段小程序:

#include <stdio.h>

int main() {
    printf("Hello, World!\n");
    return 0;
}

编译,生成可执行文件:

gcc hello.c -o hello

运行一下:

./hello

看看:

hello, World!

记得那会大一,是用VC++6.0(相当古老的一个工具了)开始写代码的,当黑漆漆的窗口出现在面前的时候,第一反应是激动,而后才是好奇:好奇为什么我们通过键盘输入的字符会产生如此效果;好奇什么是编译、链接;好奇为什么要这么做才可以生效。一开始的问题不是很多,因为当时了解的还不够深、学得不够多。等待后来,随着学习的深入,新的疑问又从脑海里冒出:

  • 为什么源代码需要编译才能运行?
  • 为什么要有编译器、链接器?编译出来的到底是什么?
  • 程序在计算机里是怎么执行的?
  • 为什么不同操作系统上的程序不能互用?
  • #include <stdio.h>做了什么?和#include "stdio.h"的区别是什么?printf()是怎么实现的?
  • ……

当时没有学过计算机组成原理,没有学过操作系统,数据结构和算法只是听说却用的不多。于我而言,计算机中有太多的秘密,仿佛像层层轻纱遮盖住了什么,吸引我去掀开它、去了解它。

如今,这本书能够对我脑海中的疑惑做出一些解释。

计算机的硬件组成

没有硬件的软件是空中楼阁。一般,一个计算机主要由四大部分组成:

  • CPU:计算机的大脑,负责算术运算和逻辑运算
  • 内存:对应的英文是Memory,程序运行时存放的位置
  • 总线:对应的英文时Bus,计算机各部件通信的桥梁
  • I/O设备:Input/Output设备,用于计算机与外界进行交互

早期CPU由于核心频率不高,往往是和内存、I/O设备挂在同一总线上。为了适应接口不同、速率不同的I/O设备,也为了让CPU能够和I/O设备进行通信,一般一个I/O设备都会有一个对应的I/O控制器。

后来CPU核心频率飞速发展,远远高于内存、I/O设备的传输频率。计算机系统设计师根据速率将总线一分为二,用一个负责低俗设备的连接,称为南桥芯片;另一个负责高速设备的连接,称为北桥芯片。南桥芯片挂载到北桥上,作为北桥上的一个设备来看代。

单个核心频率由于CPU制造工艺,存在一个物理瓶颈。早期一个物理的CPU只有一个物理核心,于是人们开始想办法,使用多CPU架构的计算机系统,来提升计算处理速度。最常见的就是对称多处理器(SMP,Symmetrical Multi-Processing),简单说就是每个CPU在系统中所处的地位和所发挥的功能都是一样的,是相互对称的。但是这种计算机系统对操作系统的要求十分高,因为它的思想是想提高速度,需要把计算机程序分成若干个相互独立的部分,分别交由不同的CPU执行,从而加快执行速度,这在一些大型数据库、大型网站服务器上有奇效,然而不是对所有的程序都有帮助。芯片厂商为了提高处理器的性能,于是设计出了多核处理器(Multi-Core Processor),实际上它是SMP的简化版。

问:处理器中,什么才可以叫做一个核心?是如何区分的?处理器的频率是如何决定的?从微观上解释是如何起作用的?换句话说,单条机器指令如何被处理器解释并执行的?

计算机软件结构体系

软件是计算机硬件的灵魂。一般软件可分为系统软件和用户软件,但其实它们的界限比较模糊,不用较真。

整个计算机系统的设计充分体现了分层的思想——硬件分层、软件分层。

从软件体系结构上看,一个(还有很多种分层方式)计算机系统从下到上可分为:硬件层——系统层——运行时库——应用。

层与层之间通信(肯定要通信)就不要有一个通信协议,一般称为接口。接口的下方是接口的提供者,上方是接口的使用者。各层无需管与它无关的其他层具体是如何实现的,只要按照接口标准去使用接口、定义接口即可。

运行时库使用操作系统提供给的系统调用(System Call)为应用提供应用程序编程接口(API,Application Programming Interface)。硬件提供的接口往往被叫做硬件规格(Hardware Specification)

操作系统

操作系统的作用是为了充分利用系统资源(主要是CPU),负责各应用程序之间的资源调度。

相关概念:多道程序设计(Multiprogramming)、分时系统(Time-Sharing System)、多任务系统(Multi-Tasking System)、抢占式(Preemptive)。

为了某些需求操作系统会引入一些功能,比如为了简化编程和应用安全,操作系统引入了虚拟地址空间、地址空间隔离技术;为了同时运行多个程序,需要将它们加载进入内存,出现了分段、分页技术。

多线程、多进程

为何要单独拎出来说?可以看到,前面这么多花里胡哨的操作,其目的都是为了充分使用计算机,充分发掘计算机的计算能力。通过众多的分析研究,人们发现软件不是时时刻刻都需要使用CPU,比如它们在进行繁重的I/O操作;还有软件可能某时刻需要长时间的计算,另外还需要处理与用户的交互。随着单颗物理CPU核心数的增多,毫无疑问,多线程、多进程技术也是吸引程序设计者的一个热点方向。

在此只是提一下,不会深入分析。如果这个要聊起来,涉及到概念、技术手段、安全等等,一篇文章肯定是不够的。暂且留个坑吧。