裸机和实时操作系统(RTOS)不同
假设要完成这样一个项目:打游戏(假设一局游戏10分钟)和回复老板信息(假设回消息1分钟)。针对裸机和实时操作系统二者来说都会如何完成这样一个项目呢。
裸机说,这个简单,说罢,他给出了这样的代码。
while (1)
{
打游戏;//需要10分钟
回消息;//需要1分钟
}
结果就是队友骂他挂机,老板炒了他鱿鱼。为什么会这样呢?
原来裸机把打游戏和回消息这两个任务放在了一个死循环中执行。只有打游戏完成之后才会回消息,回完消息才能打游戏。对于队友来说,每过10分钟就有1分钟的挂机时间,对于老板来说,每过10分钟才会回复一条消息。当然会引起队友和老板的不满了。
而实时操作系统就聪明多了。他是这样干的,代码如下。
int main()
{
创建游戏任务;
创建回复消息任务;
return 0;
}
void 打游戏()
{
while (1)
{
打游戏();
}
}
void 回复消息()
{
while (1)
{
回复消息();
}
}
他先是在主函数中创建了两个任务,分别是打游戏和回复消息的任务。
之后将打游戏和回复消息的具体操作写在了两个死循环里面,之后每个任务分配给他1个时间片(1ms,该时间可以自己设置)的时间去执行。这样,对于老板来说,每隔1ms总能收到消息,对于队友来说,每隔1ms你就在线。但是由于这1ms时间太短,就造成了这样的错觉:老板认为你一直在回复消息,队友认为你一直在打游戏。这就是实时操作系统相对于裸机的聪明之处。
如果此时你突然要去医院(需要1个小时),裸机和实时操作系统又会怎么处理呢?
裸机会将去医院这样一个事情放到中断里面去执行。但是在中断中执行1小时的事情,显然不可能。最好的办法是在去医院的中断给一个标志位赋值。建议中断中执行flag = 1;之后在循环中判断flag是否等于1,等于1的话去医院。
while(1)
{
打游戏;
回消息;
if(flag == 1)
{
去医院;
}
return 0;
}
`但是这样也会有一个问题。如果单片机在执行打游戏这样一个操作的时候进入了中断,在中断中给flag赋值为1,之后程序从中断中返回到程序中时,依旧要先执行打游戏和回消息,之后才能执行去医院的操作。这样的话去医院的事情就会被搁置了,保证不了实时性。
而对于实时操作系统来说,他是这样办的
int main()
{
创建游戏任务;
创建回复消息任务;
创建去医院任务;
return 0;
}
void 打游戏() 优先级是低的
{
while (1)
{
打游戏();
}
}
void 回复消息() //优先级是低的
{
while (1)
{
回复消息();
}
}
void 去医院() //优先级是高的
{
while (1)
{
回复消息();
}
}
他依旧会创建打游戏,回消息和去医院三个任务,只不过去医院的任务优先级比较高。只要去医院这个任务准备好,就会立马执行,从而保证实时性。但是在去医院的过程中要打车(类似于延时函数),在车上也可以打游戏和回消息。实时操作系统可不会让程序一直等着,他会在去医院的延时过程中把CPU的使用权重新给到打游戏和回消息。直到去医院的延时函数到了时间,操作系统会把CPU使用权重新给到去医院这样的任务。而确定谁能执行任务的东西叫任务调度器。
裸机和实时操作系统(RTOS)特点
裸机
裸机是前后台系统,中断服务函数是前台,while大循环是后台系统,中断可以打断后台系统的执行,中断执行完成之后,依旧会回到离开程序进入中断的位置,从而接着执行之后的任务。
但是这样有以下几个缺点:
- 实时性差(程序在while循环中必须一句一句的执行)
- 空等待(延时函数什么也执行不了)
- 程序臃肿(所有的程序都在while循环中)
对于实时操作系统,主要讲究的就是实时性。- 分而治之——将一个项目分为一个一个的任务完成,每个任务都是无限循环的。
- 任务调度——延时函数不空等待
- 抢占式——给每个任务分配各自的优先级。同一优先级的任务可以有多个。高优先级可以打断低优先级的任务。
- 任务堆栈——每个任务都是有自己的栈,用于保存任务切换时的数据(局部变量和任务上下文信息)。
- 中断可以打断所有任务。
初步了解UCOS-III
ucos-III是基于C语言编写的第三代小型系统,在他前面还有两代,下表列出了3者不同,简单了解即可。总的来说ucos-III是可裁剪,没有任务限制的可剥夺(抢占式)的多任务系统。