上周看完了《计算机是怎样跑起来的》这本书,初看时真的很惊艳。这本书很好地概述了计算机的执行过程,特别是前几章,简化并模拟了计算机的运行。因此,在这里简单总结下这本书的内容。
计算机三原则
作者将计算机的执行过程用3个原则概括了:
- 程序是指令和数据的集合
- 计算机是执行输入、运算、输出的机器
- 计算机的处理方式有时跟人的思维方式不一样
这三个原则贯穿了整本书。
简单的计算机系统
接下来,作者用一个简易的电路图来描述并模拟计算机的运行。里面包括CPU、内存、IO、时钟发生器、外接设备,借助这个简易系统讲解了DMA(不经CPU直接外部访问内存)、中断(硬件通知接口,避免一直监听IO)这些基础知识。能更直观跟底层地理解到知识。CPU、内存、IO中不仅有地址总线引脚、数据总线引脚,还有控制引脚。
备注:处理中断请求的程序,要么内置在被烧录在计算机ROM的BIOS系统中,要么内置于windows等OS中。——>计算机具有硬件上处理中断的能力。
编程语言
作者还借助这个系统讲解了汇编语言:
- 寄存器是用来存储数据,内存需要通用寄存器来跟IO交互。
- 每一句汇编语句由指令跟操作数组成,操作数可以是寄存器,也可以是立即数。
- 每个汇编指令在CPU说明书都有对应的二进制编码,会转为二进制完成对应的执行流程。
- 一旦重置CPU,CPU会从0号地址开始顺序执行程序。
CPU的寄存器不仅可以存储数据,还具备对数据进行运算的能力。CPU的寄存器种类取决于CPU的种类。常见寄存器种类:A累加寄存器、F标记寄存器、PC程序指针、SP栈顶指针。
小端序时低位在前,高位在后;大端序相反,具体哪种取决于CPU种类。
汇编语言是一个机器语言,比较接近计算机的执行过程,但不容易维护跟理解。因此在此基础上,有C语言这类面向过程的语言(条件/循环/顺序),编写过程更简单,可以通过流程图阐述代码的执行流程。不必编写类似JMP等一堆冗长的汇编语言。
结构化程序设计就是“仅用顺序执行、条件分支和循环表示程序的流程即可,而不再使用跳转指令goto”(底层汇编仍有JMP)。顺序执行是最基本的程序流程,因为CPU中的PC寄存器会自动更新,而条件跟循环可以通过跳转指令表示,硬件上即将这些PC的值设为跳转的目的地内存地址即可。
在C语言基础上,还有C++、Java等面向对象的语言,这类语言更接近人类世界的理解。将每个实体抽象为一个对象,利用继承、多态、封装三大特性去进行编程,使复杂系统更容易维护和扩展。可以用UML(Unified Modeling Language)来设计程序。
算法&数据结构
接下来,作者还简单地介绍了算法,定义为“被明确定义的有限个规则的集合,用于根据优先步骤解决问题”。介绍了一些经典算法(辗转相除法、排序算法),推荐我们去学习牢记一些经典算法的同时,要自发地去思考算法的解法。提到了一个算法技巧--哨兵,用于线性搜索等算法中减少判断(在最后一位设置为欲查找数,保证一定跳出循环)。
提到算法,自然离不开数据结构,书中还介绍了一些常见的数据结构如数组、链表、队列、栈、结构体、二叉树这些。这些都是计算机的基础,就不赘述了。
数据库&网络
此外,文中还介绍了数据库跟网络。都只是简单地过下要论,比如数据库SQL语句、DBMS的优点、键和索引这些。通过关系型数据库可以在一个数据库中避免重复存储相同的数据,用主键跟外键在表间建立关系。索引表是一种结构,存储字段值跟字段对应记录的位置,可以更快地进行数据的检索跟排序。
网络部分过的比较详细,比如ARP、CSMA/CD、DHCP、DNS、TCP、IP这些基础协议的执行原理。每个网卡带的ROM上预先烧录了一个唯一确定的MAC地址。在TCP/IP网络中,传输数据都会带MAC和IP两个地址。子网掩码用于区分IP地址的网络位和主机位。
加密算法&XML
接下来,文中简单地介绍了下加密算法,对称加密和非对称加密(公钥&私钥)、以及数字签名这些基本概念。常见的RSA算法如下,当c的位数足够多时,解出a、b的时间就会快速上升。数字签名与常规传输相反,用私钥加密,公钥解密。
之后,作者还介绍了XML这个语言。XML是扩展标记性语言,相较于HTML(超文本标记语言),它的标签具有扩展性,可以支持各种自定义标签;而HTML只是固定的一些标签。
因此,XML的应用范围更广泛些。XML的数据是纯文本格式的,只包含字符。可以用"xmlns=明明空间的名字"作为标签的一个属性记述,为标签设定命名空间,避免命名冲突。XML可以用DTD或schema来约束XML文档,用于检查格式、数据类型跟位数等。
还有一类文件类型——CSV——则只是由逗号跟换行符分割开来,在一些数据存储上(如算法的数据集)也很常用。
SE
最后,文中介绍了SE(系统工程师)跟普通的软件开发工程的区别,系统工程师类似项目管理+架构师的角色,需要关注用户需求、整个系统的设计跟模块拆分、去推动需求的执行跟落地;而软件开发工程师更在意代码编程,在乎数据库跟网络这一类功能。两者的发展路线会有比较大的差异。