硕士期间对程序如何从编码到最终运行有强烈的好奇心,也在编译技术方面做了相应的研究工作,硕士毕业的论文是关于编译技术,当年毕业就希望从事编译技术相关工作,怎奈当时极少有此方面的岗位。
工作后为弄清进程如何在操作系统中运行的,有幸加入新设计团队,在杨力祥老师的带领下完成《Linux内核设计的艺术》一书,并由机械工业出版社出版发行,得到业界的肯定与赞誉,英文版被MIT等100多所大学和美国国会图书馆收藏。
随后我也意气风发准备去IBM从事z/OS的工作,后来鬼使神差地被华为人力的一句话打动了——“您去IBM,美国人会把核心技术放到中国吗?我们华为要做一个分布式数据库,需要开发一个分布式文件系统,我们舞台很大,您可以尽情发挥自己的聪明才智”。之后我加入华为2012实验室华为高斯开发部从事GuassDB的架构设计与研发。

就此凑齐了IT基础软件的三件套全家桶——编译器、操作系统和数据库。
众所周知,程序是开发者编码,之后由编译器编译代码和链接后形成可执行文件。在执行时,先由操作系统通过加载器创建进程(线程可以看做广义的进程,本文以进程进行说明)后再加载程序的可执行文件、把程序计数器PC指向程序入口地址,最后CPU按照指令集执行。
但,编译器、操作系统到底是如何做到这些的?它们的设计思想是怎样的?今天,我尝试着来解释下。
图:编译器、操作系统、数据库三大基础软件的设计思想与CPU间的关系
一、编译器是把开发者用编程语言遵照语法规则编写的代码转换成CPU认识的按相关规则组织的CPU可执行文件(如:Window的PE格式文件、Linux的ELF格式文件等)。
从这个过程我们可以看出,从人认识的规则到CPU认识的规则,人需要学习编程语言的规则后,才会懂得代码的含义,而计算机只能一个个字符读取开发者开发的源码——XT时序结构,进行词法和语法分析形成内存中的XY空间结构——把关联信息保留在空间结构中,最后再把XY空间结构信息转换成XT时序结构,最后经过链接器生成可执行文件(如:PE格式、ELF格式等)。
即:编译器的本质是计算机把它读取的XT时空结构的源码信息无损的转换成XY空间结构,再由XY空间结构无损的转换成CPU可执行的XT时空结构的可执行文件,见图中第一部分。
二、操作系统要解决实时多任务的问题——在资源有限的情况下,如何解决并发使用资源,保证资源的一致性,提高资源使用率。为解决此问题,操作系统采用如下的设计思想。
1、以碎治碎,把CPU分成时间片、内存分成页、硬盘分成块等,任务按需求申请和释放,操作系统按小块的分配和回收。
2、主奴机制,用户任务抽象成进程,操作系统对进程进行组织、管理、协调,进程可以申请资源,如:内存、磁盘等,但分配不分配的操作系统这个“主子”说了算,进程何时运行也是由操作系统“主子”说了算,即主奴机制,规则简单,效率高,如需进一步提高效率则需进一步提高精细化管理。
3、定位识别,按约定,在固定的位置按照约定的规则解读字段信息,如:电脑重新上电时,程序计数器PC指向0X7C00,约定到固定的位置去读取BIOS信息。
4、定长管理变长,通过定长信息,描述后面的变长信息有多长,如:磁盘格式化后,在头部约定的几个数据块即超级块,对整个磁盘的情况进行描述,如文件格式、inode节点情况、块空间使用情况等。
即:操作系统的本质把并发任务抽象成进程,通过“以碎治碎、主奴机制”的设计思想,对进程进行组织、管理、协调,保证资源使用的一致性,提高资源利用率,见图中第二部分。
三、当操作系统通过创建进程,加载编译器编译好的可执行文件,经过操作系统的调度,当进程获得CPU时间片可以执行时,则CPU就按指令执行,见图中第三部分。
至此,一个程序从编译、链接、加载、调度、执行、退出的完整生命周期就讲解完毕。
四、关系型交易型数据库(以下简称数据库),如PostgreSQL、MySQL等,要解决并发访问数据时,保证数据的一致性,提高系统的并发量和吞吐率。其采用的设计思想与操作系统的设计思想是一致的——“操作系统解决的是对硬件资源的竞争,数据库要解决对数据资源的竞争”,本质上是同源的。具体体现如下:
1、以碎治碎,把表分成page和行、缓冲区分成page、表的物理存储分成page和行等,任务按需求申请和释放,数据库按小块块“小块块”的分配和回收。
2、主奴机制,用户任务抽象成事务,数据库依托操作系统的进程对事务进行组织、管理、协调,事务可以申请资源,如:缓存、数据空间等,但分配不分配得数据库这个“主子”说了算,事务何时运行也是由数据库“主子”说了算,即主奴机制,规则简单,效率高,如需进一步提高效率则需进一步提高精细化管理。
3、定位识别,按约定,在固定的位置按照约定的规则解读字段信息,如:每个物理page的头部留出一些字段信息描述page里面的情况。
4、定长管理变长,通过定长信息,描述后面的变长信息有多长,如:通过每个物理page的头部信息,来描述page中tuple的位置和长度,这也是数据库能灵活实现用户定义行数据大小的基础。
即:数据库的本质把并发任务抽象成事务,通过“以碎治碎、主奴机制”的设计思想,对数据库进行组织、管理、协调,保证数据资源使用的一致性,提高效率和系统吞吐率,见图中第四部分。
当要执行一条”select from t”SQL时,则客户端首先通过JDBC等发起一个连接请求,数据库服务器端接受请求,向操作系统申请创建一个子进程,子进程启动事务(假设默认启动事务),接受请求SQL,执行词法分析、语法分析、优化、执行等,最后返回结果给用户。从中可以看出与编译器和CPU有很多关联性。
至此,编译器、操作系统、数据库三者之间的设计思想以及与CPU的关系介绍完毕,我们总结如下,见图中第五部分:
1、数据库与操作系统:设计思想相似,事务与进程概念同构,他们都是任务的体现。
2、数据库与编译器:SQL引擎的词法、语法分析与编译器的词法、语法分析是一致的。
3、数据库与CPU:数据库的执行引擎、算子与CPU的执行、指令集思想上是同源的。
可以看出,在技术上也印证了“太阳底下无新鲜事”,技术上很多事情都是相通的,而数据库是集大成者之一。
我曾对团队说过,应届毕业就从事数据库内核的研发工作,是不幸也是有幸。不幸的是数据库知识庞杂、技术太难,入门都很难。幸运的是数据库体系性很强,同时几乎我们学过的所有IT知识都会在数据库中体现,如果在数据库的锤炼下能坚持下来,在技术上必有所成。
编译器、操作系统和数据库三大基础软件设计如此精妙,不失为自身提高的好案例。
共勉!