我是靠谱客的博主 敏感云朵,这篇文章主要介绍有限状态机的编程原理及编程实例,现在分享给大家,希望可以做个参考。

有限状态机

有限状态机解决的问题是复杂流程。
简单流程:自然流程是结构化的,按照人类顺序思维解决的问题。
复杂流程:自然流程不是结构化的,比如先前的MultiButton。

具体实例

在linux操作系统下实现终端设备界面相互切换。实现读取fd1的数据写入的fd2中,读取fd2的数据写入到fd1当中。

状态机简单示意图如下所示:
在这里插入图片描述

实验工程源码

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <errno.h> #define TTY1 "/dev/tty11" #define TTY2 "/dev/tty12" #define BUFSIZE 1024 /*********状态机状态枚举类型**********/ enum { /*文件读状态*/ STATE_R = 1, /*文件写状态*/ STATE_W, /*异常终止态*/ STATE_Ex, /*退出态*/ STATE_T }; /*********状态机结构体**********/ struct fsm_st { /*状态机状态*/ int state; /*源文件描述符*/ int sfd; /*目标文件描述符*/ int dfd; /*读取长度*/ int len; /*位置*/ int pos; /*报错信息*/ char * errstr; /*buf缓冲区*/ char buf[BUFSIZE]; }; /***********************启动状态机*****************/ static void fsm_driver(struct fsm_st*fsm) { int ret; switch (fsm->state) { /*状态机读取*/ case STATE_R: /*读取到的源fd存储到buf中*/ fsm->len = read(fsm->sfd,fsm->buf,BUFSIZE); /*如果读取0字节,退出状态机*/ if (fsm->len == 0) fsm->state = STATE_T; /*如果读取<0字节,进行状态判断*/ else if (fsm->len < 0) { /*如果读取<0字节,二次判断*/ if (errno == EAGAIN) fsm->state =STATE_R; else { /*宕机退出*/ fsm->errstr = "read()"; fsm->state =STATE_Ex; } } else /*都没有报错,说明读取正常,则开始状态机写入*/ { /*******初始化写入的位置为0***************/ fsm->pos = 0; fsm->state =STATE_W; } break; /*状态机写入*/ case STATE_W: /*写入读取到的数据len*/ ret = write(fsm->dfd,fsm->buf+fsm->pos,fsm->len); /*写入读取到的数据<0*/ if(ret < 0) { /*假的错误*/ if (errno == EAGAIN) /*再次进入写入*/ fsm->state = STATE_W; else /*真正读取错误*/ { /*读取错误*/ fsm->errstr = "read()"; /*宕机退出*/ fsm->state =STATE_Ex; } } else /***************坚持写够len个字节数***************/ { /*******从pos的位置继续向下写入字节***************/ fsm->pos += ret; fsm->len -= ret; /*如果写入完成*/ if(fsm->len == 0) /*返回读态*/ fsm->state = STATE_R; /*否则返回写态,继续写够len个字节*/ else fsm->state = STATE_W; } break; /*宕机退出*/ case STATE_Ex: perror(fsm->errstr); fsm->state = STATE_T; break; /*完整退出*/ case STATE_T: /*do sth*/ break; default: /*如果都不是以上任意一个状态,发送异常*/ abort(); break; } } static void relay(int fd1,int fd2) { int fd1_save,fd2_save; /*读左写右和读右写左状态机*/ struct fsm_st fsm12,fsm21; /***********************************************/ /*保证两个文件是以非阻塞方式实现*/ /*fcntl函数的作用是获取文件状态信息*/ fd1_save = fcntl(fd1,F_GETFL); fcntl(fd1,F_SETFL,fd1_save|O_NONBLOCK); fd2_save = fcntl(fd2,F_GETFL); fcntl(fd2,F_SETFL,fd2_save|O_NONBLOCK); /***********************************************/ /******************状态机初始化状态********* *****/ fsm12.state = STATE_R; fsm12.sfd = fd1; fsm12.dfd = fd2; fsm21.state = STATE_R; fsm21.sfd = fd2; fsm21.dfd = fd1; /***********************************************/ /*******************推动状态机*******************/ while (fsm12.state != STATE_T ||fsm21.state != STATE_T ) { fsm_driver(&fsm12); fsm_driver(&fsm21); } /***********************************************/ /******************恢复起始默认状态**************/ fcntl(fd1,F_SETFL,fd1_save); fcntl(fd2,F_SETFL,fd2_save); /***********************************************/ } int main() { int fd1,fd2; /*模拟用户打开设备*/ fd1 = open(TTY1,O_RDWR); if (fd1<0) { perror("open()"); exit(1); } write(fd1,"TTY1n",5); /*模拟用户打开设备,以非阻塞方式打开设备*/ fd2 = open(TTY2,O_RDWR|O_NONBLOCK); if (fd2<0) { perror("open()"); exit(1); } write(fd2,"TTY2n",5); /*中继引擎函数*/ relay(fd1,fd2); close(fd2); close(fd1); exit(0); }

最后

以上就是敏感云朵最近收集整理的关于有限状态机的编程原理及编程实例的全部内容,更多相关有限状态机内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(89)

评论列表共有 0 条评论

立即
投稿
返回
顶部