确定性自动机¶
形式上,一个确定性自动机,用 G 表示,定义为一个五元组
G = { X, E, f, x0, Xm }
其中
X 是状态的集合;
E 是事件的有限集合;
x0 是初始状态;
Xm (X 的子集)是标记(或最终)状态的集合。
f : X x E -> X 是转换函数。它定义了在状态 X 中发生来自 E 的事件时的状态转换。在确定性自动机的特殊情况下,在 X 的状态中发生 E 中的事件,其下一个状态是确定的来自 X 的状态。
例如,一个名为 ‘wip’(抢占式唤醒)的给定自动机可以定义为
X = {
preemptive
,non_preemptive
}E = {
preempt_enable
,preempt_disable
,sched_waking
}x0 =
preemptive
Xm = {
preemptive
}- f =
f(
preemptive
,preempt_disable
) =non_preemptive
f(
non_preemptive
,sched_waking
) =non_preemptive
f(
non_preemptive
,preempt_enable
) =preemptive
这种形式化定义的好处之一是,它可以以多种格式呈现。例如,使用顶点(节点)和边的图形表示,这对于操作系统从业者来说非常直观,没有任何损失。
前面的 ‘wip’ 自动机也可以表示为
preempt_enable
+---------------------------------+
v |
#============# preempt_disable +------------------+
--> H preemptive H -----------------> | non_preemptive |
#============# +------------------+
^ |
| sched_waking |
+--------------+
C 语言中的确定性自动机¶
在论文 “Linux 内核的高效形式化验证” 中,作者提出了一种在 C 语言中表示自动机的简单方法,该方法可以用作 Linux 内核中的常规代码。
例如,’wip’ 自动机可以表示为(带有注释)
/* enum representation of X (set of states) to be used as index */
enum states {
preemptive = 0,
non_preemptive,
state_max
};
#define INVALID_STATE state_max
/* enum representation of E (set of events) to be used as index */
enum events {
preempt_disable = 0,
preempt_enable,
sched_waking,
event_max
};
struct automaton {
char *state_names[state_max]; // X: the set of states
char *event_names[event_max]; // E: the finite set of events
unsigned char function[state_max][event_max]; // f: transition function
unsigned char initial_state; // x_0: the initial state
bool final_states[state_max]; // X_m: the set of marked states
};
struct automaton aut = {
.state_names = {
"preemptive",
"non_preemptive"
},
.event_names = {
"preempt_disable",
"preempt_enable",
"sched_waking"
},
.function = {
{ non_preemptive, INVALID_STATE, INVALID_STATE },
{ INVALID_STATE, preemptive, non_preemptive },
},
.initial_state = preemptive,
.final_states = { 1, 0 },
};
转换函数表示为状态(行)和事件(列)的矩阵,因此函数 f : X x E -> X 可以在 O(1) 中求解。例如
next_state = automaton_wip.function[curr_state][event];
Graphviz .dot 格式¶
Graphviz 开源工具可以使用 (文本) DOT 语言作为源代码生成自动机的图形表示。DOT 格式被广泛使用,可以转换为许多其他格式。
例如,这是 DOT 中的 ‘wip’ 模型
digraph state_automaton {
{node [shape = circle] "non_preemptive"};
{node [shape = plaintext, style=invis, label=""] "__init_preemptive"};
{node [shape = doublecircle] "preemptive"};
{node [shape = circle] "preemptive"};
"__init_preemptive" -> "preemptive";
"non_preemptive" [label = "non_preemptive"];
"non_preemptive" -> "non_preemptive" [ label = "sched_waking" ];
"non_preemptive" -> "preemptive" [ label = "preempt_enable" ];
"preemptive" [label = "preemptive"];
"preemptive" -> "non_preemptive" [ label = "preempt_disable" ];
{ rank = min ;
"__init_preemptive";
"preemptive";
}
}
可以使用 dot 实用程序将此 DOT 格式转换为位图或矢量图像,或者使用 graph-easy 转换为 ASCII 艺术。 例如
$ dot -Tsvg -o wip.svg wip.dot
$ graph-easy wip.dot > wip.txt
dot2c¶
dot2c 是一个实用程序,它可以解析包含自动机的 .dot 文件(如上例所示),并自动将其转换为 [3] 中提出的 C 表示形式。
例如,将前面的 ‘wip’ 模型放入名为 ‘wip.dot’ 的文件中,以下命令会将 .dot 文件转换为 ‘wip.h’ 文件中 C 表示形式(先前显示)
$ dot2c wip.dot > wip.h
‘wip.h’ 的内容是 ‘C 语言中的确定性自动机’ 部分中的代码示例。
备注¶
自动机形式允许以多种格式对离散事件系统 (DES) 进行建模,适用于不同的应用程序/用户。
例如,使用集合论的形式描述更适合于自动机运算,而图形格式更适合于人工解释;以及用于机器执行的计算机语言。
参考资料¶
许多教科书都涵盖了自动机形式。有关简要介绍,请参阅
O'Regan, Gerard. Concise guide to software engineering. Springer,
Cham, 2017.
有关详细描述,包括离散事件系统 (DES) 上的操作和应用,请参阅
Cassandras, Christos G., and Stephane Lafortune, eds. Introduction to discrete
event systems. Boston, MA: Springer US, 2008.
有关内核中的 C 表示形式,请参阅
De Oliveira, Daniel Bristot; Cucinotta, Tommaso; De Oliveira, Romulo
Silva. Efficient formal verification for the Linux kernel. In:
International Conference on Software Engineering and Formal Methods.
Springer, Cham, 2019. p. 315-332.