目前更新到5.3节,请在http://dl.dbank.com/c02ackpwp6下载5.3节的全部文档
本节源代码请在http://dl.dbank.com/c0ss54iddw下载
第6节 任务自结束
上节增加了删除任务的函数MDS_TaskDelete,任务可以调用该函数结束其它任务或自身任务的运行。在前面章节我们说过,目前任务还不具备自结束功能,需要使用类似while的结构循环运行。本节我们将增加任务自结束功能,在创建任务时不再受任何限制。
任务要做到自结束,需要解决2个问题,一,任务需要能脱离操作系统的调度。二、任务在结束后,操作系统需要能发生调度,切换到下个任务继续运行。
这2个问题我们都可以像上节那样,调用MDS_TaskDelete函数解决,但如果使用MDS_TaskDelete函数来实现任务的自结束,那么MDS_TaskDelete函数就必须以显式的方式写在每个任务主函数的最后一行,当任务运行到结束时,任务会运行MDS_TaskDelete函数结束自身的运行。这样做有一个明显的缺点,我们需要为每个任务增加这样一行代码,不但对用户进行了约束,使用不方便,而且如果用户忘记了增加这行代码,那么操作系统运行到任务结束后就会崩溃掉。
前面我们介绍过,LR寄存器中保存的是本函数返回上级父函数的PC指针,返回父函数时只要跳转到该PC指针就可以了。如果我们要做到任务自删除,那么就可以借用这个功能,可以将MDS_TaskDelete函数认为是每个创建任务所使用的主函数的父函数,在任务初始化时,将MDS_TaskDelete函数的地址赋给LR寄存器,这样当任务运行完最后一条指令时,它就会取出LR寄存器中的MDS_TaskDelete函数的地址,跳转到MDS_TaskDelete函数,实现任务的自结束功能。这种方式是隐式的,不会对用户做任何限制,只需要我们修改MDS_TaskStackInit函数代码,增加对LR寄存器的初始化就可以一劳永逸了。
00011
00012
00013
……
00032
00033
00034
……
00043
00044
MDS_TaskStackInit函数的改动量非常小,只需要在33行将MDS_TaskSelfDelete函数赋给LR寄存器。MDS_TaskSelfDelete函数封装了MDS_TaskDelete函数,将存放当前指针的全局变量gpstrCurTcb传给MDS_TaskDelete函数,完成任务的自删除。
00191
00192
00193
00194
本节的改动已经介绍完毕,本节的验证函数与上节非常相似,其中TEST_TestTask1和TEST_TestTask2函数与上节完全一样,TEST_TestTask3函数修改为只循环6次,每次循环时间为1000
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
除此之外root任务也不需要再调用MDS_TaskDelete函数自我删除,也是由本节新增加的隐式删除方式进行自删除。
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
本节运行结果截图如下:
读者可以访问http://blog.sina.com.cn/ifreecoding网站下载视频,观看全部数据的打印过程,
可以看到本节实际运行打印出的结果与我们上节的实际运行打印出的结果是一致的,这也是与我们设计相符的,但这里还是有一点稍微的不同,见图51:
图51左边是上节打印输出的数据,右边是本节打印输出的数据,这两组数据对比的结果如图51所示,只有90和92行的结果不同。上节当系统运行到8000
图51的截图是Beyond
使用工具软件解析本节任务切换过程的数据,结果如下图所示:
对比上节中任务切换过程的图49,可以明显的看出在8000