前言:
你看到这个题目肯定会有一个问题
why:我为什么要学状态机?
如何要我说为什么要学状态机?那我用一句话来回答:有了这个概念,你就能对程序如何在计算机上运行建立基本认识
我最早见到这个词是在nju的pa实验文档上(那还是我大二的时候,我当时还在看csapp的书,看到第八章exception control flow异常控制流有点看不懂,在网上偶然看到袁春风老师的计算机系统基础课,顿时感觉豁然开朗,后来知道他们ics有一个实验叫pa。不过惭愧的是pa我没真的做完,第二个lab x86的实现太恐怖了。不过nju愿意把这样的实验开源出来,我只能说nju相当于中国的cmu)
后来我在b站上听jyy的os课,说fork是无情的复制状态机的机器,说execve是重置状态机。(不得不说我被这种高贵的授课方式所打动了,这比我以往任何听到的讲fork的方法都要美,简直达到了一种无言自证的程度。)
不过要理解这句话,脑子里要有2.5个公式:
计算机是个状态机
程序是个状态机
操作系统是个状态机(因为os就是跑在freestanding上的程序,所以只算0.5个)
你现在脑子里肯定有一个问题
what:什么是状态机?
有限状态机(英语:finite-state machine,缩写:FSM)又称有限状态自动机(英语:finite-state automaton,缩写:FSA),简称状态机,是表示有限个状态以及在这些状态之间的转移和动作等行为的数学计算模型。
(有限状态机 - 维基百科,自由的百科全书 (wikipedia.org))
是不是有点懵?没事这只是我从wiki上扒下来的(正经人谁学习靠wiki)
这个状态机或者叫自动机是来自于一门叫计算理论的课,如果你对这个很感兴趣,我这有一本秘籍可传授于你

秘籍: 《introduction theory of computation》 by Michael Sipser 中文名叫计算理论导论
b站上有作者亲授课程(【MIT18.404】计算理论基础(完结)—理论研究或算法应用的基础课哔哩哔哩bilibili)
不过话说回来我们的名字叫浅尝状态机,那肯定只讲状态机。还记得我最早是在哪里看到状态机的?没错就是在pa的文档上,如果能让那个写文档的人(pa的实验文档是一个叫yzh的大佬写的)来向我们解释状态机,那不是极好的。
本来是没这个可能的,不过现在yzh和别人一起组织了一个叫“一生一芯”的活动(这个活动也好像办了几年了)b站上刚好有他们的录播课,其中正好有讲到状态机模型。(他们愿意干这样的事情,我很佩服,并且也很感谢他们能把这些资料开源出来)
现在回到我们的问题 什么是状态机?

我们举一个灯泡的例子
状态集合:灯泡的状态无非亮灭
激励事件:改变状态的事件,在这里是开关的开和关
状态转移规则:就是现在状态的次态,亮的次态是灭,反之亦然
初态:可以通过电路图看出
有没有感觉状态机的定义有一丝熟悉呢?反正我是感觉和真值表一样一样的
只是真值表是静态的,而状态机的视角是动态的
另外可以说明这个系统是状态机
计算机系统中的状态机模型
宏观的来说:计算机是个状态机
这里的计算机就是最简单的图灵机(那个无线纸带的),不过在这里要作为一个最简单的真实计算机需要满足哪些条件:
- 结构上, TRM有存储器, 有PC, 有寄存器, 有加法器
- 工作方式上, TRM不断地重复以下过程: 从PC指示的存储器位置取出指令, 执行指令, 然后更新PC
还记得我们上面提到的灯泡结构吗?我们既然承认它是状态机,那我们也得承认计算机也是状态机
why?为什么?怎么就要承认了?(素质三联)
不急让我们慢慢说,我们上面的灯泡可以通过开关来实现亮灭,或者说可以表示1和0.有人可能会说一个1和0能干什么呢?不然,两仪生四象,二进制的力量是无穷的。不过现在灯泡的结构任然是机械式,但是如果有了布尔代数的力量,一切就会变得不一样。所有的数学和逻辑运算,加、减、乘、除、乘方、开方,等等,全都能转换成二值的布尔运算,正是依靠这一点人们才能造出电子开关。所谓电子开关就是通过电流的高低来进行回路的开关。而三级管就是这样的电子开关,(不如pnp型,就是通过e到b的电流控制e到c的电流)
可以通过三级管来构建出各种逻辑电路,而逻辑电路在布尔代数的威力下"变成"运算电路,比如加法器,而有加法器就相当于有运算器(减法通过补码变成加法,乘法就是多次的加,除就是多次的减)
那么通过加法器(这些组合逻辑)就可以计算并转移当前状态的次态。
可是我们目前数据还没地方保存,于是我们就要设计能保存自己状态的电路
现在我们就有了保存状态的部件,寄存器
计算机是一个数组逻辑电路, 那么我们可以把计算机划分成两部分, 一部分由所有时序逻辑部件(存储器, 计数器, 寄存器)构成, 另一部分则是剩余的组合逻辑部件(如加法器等). 这样以后, 我们就可以从状态机模型的视角来理解计算机的工作过程了: 在每个时钟周期到来的时候, 计算机根据当前时序逻辑部件的状态, 在组合逻辑部件的作用下, 计算出并转移到下一时钟周期的新状态.
(因为我的数学能力非常差,数电学的也不好,这一部分论证过程只是写着玩玩的,反正就记住计算机是状态机)
如果把计算机看成一个状态机, 那么运行在计算机上面的程序又是什么呢?
我们知道程序是由指令构成的, 那么我们先看看一条指令在状态机的模型里面是什么. 不难理解, 计算机正是通过执行指令的方式来改变自身状态的, 比如执行一条加法指令, 就可以把两个寄存器的值相加, 然后把结果更新到第三个寄存器中; 如果执行一条跳转指令, 就会直接修改PC的值, 使得计算机从新PC的位置开始执行新的指令. 所以在状态机模型里面, 指令可以看成是计算机进行一次状态转移的输入激励.
现在我们就可以通过状态机的视角来解释"程序在计算机上运行"的本质了: 给定一个程序, 把它放到计算机的内存中, 就相当于在状态数量为N的状态转移图中指定了一个初始状态, 程序运行的过程就是从这个初始状态开始, 每执行完一条指令, 就会进行一次确定的状态转移. 也就是说, 程序也可以看成一个状态机! 这个状态机是大状态机(所有状态的集合)的子集.
微观来说:计算机系统中的状态机模型有三层
程序
以C语言为例:c程序可以分成三部分:变量,语句,输入输出
CPU
指令集
C语言的状态机我觉得是偏静态,纯粹是靠定义的语法。
cpu还是跟我们上面说的一样,是按数字电路分的
而指令集相比于C语言,我觉得它定义的更动态,这要从指令集的组成来说,指令集除了定义指令,还包括中断异常,虚拟内存,内存模型等等,总之就是一句话定义了CPU执行指令的行为。而cpu执行指令不就是进程吗,这样想指令集定义的状态机的状态集合r和m,不就是进程所占的资源吗。 (个人愚见)
上面说fork是无情的复制状态机的机器,那fork复制的不正是当时这个状态机的状态,就是这个进程的资源(消耗极大,所以有copy on write),不过具体fork干了什么,等我在ucore里好好探索一下。
三层状态机的转换
还有一件事:虽然我们说有三层模型,但是这三层其实是等价的。就是我们程序状态机经过激励后处于的状态(次态)和经过指令集状态机激励后的次态是一样。不过不是我们说一样就一样的,这其中编译器功不可没。编译器就是保证这件事的。
我觉得我讲的还不是很清楚,直接贴一张yzh的ppt
所以在状态机的视角下,程序的运行首先是程序被翻译成指令,指令在被翻译成具体具体的电路,总结来说程序的运行就是指令在驱动着电路进行着状态的转换。
总结
说实话,我第一次看到yzh说程序的运行就是指令在驱动着电路。我感受到了一种震撼,这种感觉就像我第一次看到百年孤独的开头一样。
"多年以后,面对行刑队,奥雷里亚诺·布恩迪亚上校将会回想起父亲带他去见识冰块的那个遥远的下午"
感觉让我有种从电到计算机的"打通感",不知道这么说对不对,但是我的确是这么感觉的
其实,这个文档基本照pa文档和yzh ppt的抄的,有些地方还是直接粘的图片,不过也没办法,我水平不行也难以在原来的高山上加上自己的理解,不过这样也挺好,说不定我自己的理解还是错的,到时候来一手"取其糟粕,弃其精华"就搞笑了。不过我本人水平的确不咋地,还是强烈推荐看原文档和视频
pa文档:开天辟地的篇章 · GitBook (nju-projectn.github.io)
yzh ppt 计算机系统的状态机模型 (oscc.cc)
视频 计算机系统的状态机模型 [第五期“一生一芯”计划 - P3]哔哩哔哩bilibili
最后本期音乐推荐:Aretha Franklin 的专辑 Aretha Franklin Sings The Great Diva Classics