前后台代码结构及缺陷
前后台代码
这是最常见、最简单的单一顺序执行的代码结构, 也就是裸机程序。
后台: 在主循环中调用相应函数完成相应的操作。
前台: 主要是终端服务程序,在这里处理异步事件,时间相关性很强的关键操作必须依靠终端服务程序来保证。
存在的问题
1. 实时性不能得到保证
例如,在前台代码中有如下设置:
1
2
3
4
5
void isr (void) {
flag1 = 1;
flag2 = 1;
doSomeTings();
}
在后台代码中有如下设置:
1
2
3
4
5
6
7
8
9
10
11
int main() {
for (;;) {
if (flag1 == 1) {
doSomethingForISR1();
delay2s();
}
if (flag2 == 1) {
doSomethingForISR2();
}
}
}
在isr()中将flag1、flag2同时置1, 那么由于在处理flag1事件的时候需要延迟2S,但要求flags2事件在0.5S内处理完毕,这种情况下,flag2的事件处理就无法保证其要求的实时性
2. 存在CPU空转的情况,CPU利用率不高,白白浪费功耗
考虑如下代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
void doSomethingForISR1(void)
{
// Some Code
while (!resourceReady)
{
if (++delag >= TIME_LIMIT_1S)
{
return -1;
}
}
}
int main() {
for (;;) {
if (flag1 == 1) {
doSomethingForISR1();
delay2s();
}
if (flag2 == 1) {
doSomethingForISR2();
}
}
}
上述代码中,doSomethingForISR1()需要等待资源可用才能继续执行,这可能会白白浪费一秒钟在循环检测标志位上。
3. 强迫人按照机器的顺序工作方式思考编码。当执行的任务越多,代码结构越复杂,编码难度就越大
对于人类的思维方式来说,如果我们同时遇到多个事件需要处理,且每个事件需要一个标志位来触发,我们希望观察多个标志位,可以同时处理多个事件,当标志位触发的时候,就去处理这个事件,而不与其它事件相关,不需要去考虑,我们希望这是一个并行的过程。
但是对于前后台结构的裸机程序来说,这些事件是顺序的,导致我们必须去考虑他们的执行顺序,这让处理事件变得复杂。
裸机程序存在缺陷的根本原因
一般而言我们只有一颗CPU,所有代码都是顺序执行的,因此处理所有事件也都是顺序的
解决方案
RTOS
本文由作者按照 CC BY 4.0 进行授权