《时间触发》这本书提供的调度器最大的缺点
《时间触发》这本书提供的调度器,最大的缺点是程序之间缺少信息沟通比如如下程序,是一个调度函数
/********************************************************
×××××××××××××××调度函数×××××××××××××××××
********************************************************/
void OS_Dispatch_Tasks(void)
{uchar Index;
for (Index=0;Index<OS_MAX_TASKS;Index++) //在任务队列中循环找
{if(OS_tasks_G.RunMe>0) //如果某个任务需要运行
{ (*OS_tasks_G.pTask)();//就运行这个任务
OS_tasks_G.RunMe-=1; //运行当量减一
if(OS_tasks_G.Period==0)//如果周期等于0
{OS_Delete_Task(Index); //删除此任务
}
}
}
OS_Report_Status();//报告系统状态
// OS_Go_To_Sleep(); //进入空闲模式
}
其中有一条是删除函数程序:OS_Delete_Task(Index); //删除此任务
这个程序只是单纯的删除函数,函数退出时,并没有清理函数内部的变量,这样当再次运行函数时,由于前一次变量没有清理干净,会发生运行错误的。 这就好比手机上的安卓软件,如果你从运行程序当中直接按,强行停止程序,虽然程序停止了,但是会发生错误,比如,金山电池医生,强行停止,通知栏上的电池电量图标会永久停在通知栏上,而且电量也不再下降了,因为程序停止了。
而,如果在 全部程序界面,点清除金山电池医生内存,这时金山电池医生就停止运行,同时所有内存也清除,不会发生错误了。 我看如下 方法可能会好
(*OS_tasks_G.pTask)();//就运行这个任务
这条程序会面加一个参数,变成:(*OS_tasks_G.pTask)(OS_tasks_G.stop);//就运行这个任务
这样在程序中判断,如果是stop==1,就清除内存,并且删除本函数。 期待激烈讨论 写这本书的作者号称这是非常安全的 程序框架,
经过我的使用发现,如果避开上面提到的缺点,的确是不错,但是,很多时候我们没有办法避开这种应用,那么程序会发生 未知的 不确定的 偶然性的错误。关于这些 作者没有过多的说明,我自己也没有发现有什么更好的方法来解决。
可能,使用RTOS系统可以改变这一缺点吧,因为,这个系统任务间据说有信息传递机制。
而《时间触发》是使用了一种叫做任务队列的方法,这种方法从外部很难动用程序内部的数据。程序指针。 另外还有一种方法可以
就是添加一个程序,这个程序只运行一次,然后在这个添加程序里面再次添加两个程序,第一个只运行一次,作用是初始化,设置好内存数值,第二个才是实际程序 可重入。。。 本帖最后由 zhwm3064 于 2014-4-9 05:51 编辑
error_dan 发表于 2014-4-9 00:08
可重入。。。
就是尽量使用局部变量,使用局部变量一定是可重入的(可中断的)
如果使用全局变量 或者静态变量,就要想出种种的方法,目的是重入时,不能出错。
实际上我在6楼提供的方法就是只使用局部变量,分两个程序,头一个程序只调用一次,比如设置IO等操作,第二个程序才是主程序,这样两个程序都不包含静态变量。如果合为一个程序,必然得使用静态变量 需要自己动手修改一下,增加任务之间的通信,可以采用队列或者事件的方式。 说的有些道理 本帖最后由 coleyao 于 2014-4-9 16:25 编辑
如果任务一直运行不删除呢,如果需要任务停止一段时间可以挂起,等需要时再唤醒就好了! {:victory:}{:victory:}{:victory:} 一般来说,主要程序之间具有互斥性,所以,可以设置一个全局互斥变量,这样程序相互切换,根据互斥变量的值来确定该停哪个程序该开那个程序,这样就会好了。 这是非常老的一本书吧。好像很多年前看过。书写的非常简单。 书上的内容是不复杂,讲的东西却很实用,而且提供实例和源代码,实时os入门首选啊! 好贴》》》》》》》》》》》》》》》 这本书从传统的while(1)到理解任务调度入门的好书 别人讲的就是调度器,提供的是一种思路,一种方法,怎么用?还是要自已把握 批处理系统而已 我就只创建不删除 我看书上提供的例程全部是只添加程序,而且是一次性添加完,不删除。而我是随时添加随时删除,任务数量是动态的。现在所遇到的问题是——有些任务是不可以任意删除的,必须处理任务中的变量。这个可以实现,但是估计比较复杂,由于任务自身不可以结束自身,所以,涉及到任务与调度器之间的多次通信。1调度器发信息,指示需清除变量,2任务中清变量,并返回信息。3调度器收到信息,结束任务4调度器确认任务已结束,再添加另一任务 或者使用公用变量区,结束任务时同时清变量 函数内部的局部变量不存在这种问题吧,你退出函数变量就不存在了。如果是静态变量或者全局变量,那你用别的OS同样存在可重入问题,都是要留意的。 为毛你的任务不会自己初始化自己的运行环境?
难道你打算拿个变量不初始化就用? mangocity 发表于 2014-6-12 12:50
为毛你的任务不会自己初始化自己的运行环境?
难道你打算拿个变量不初始化就用? ...
LS正解。。。 期待讨论 长知识了。谢谢 学习了,这样的讨论交流最实用 看了一点里面的程序,如下:
tByte SCH_Add_Task(void (code * pFunction)(),
const tWord DELAY,
const tWord PERIOD)
{
tByte Index = 0;
// First find a gap in the array (if there is one)
while ((SCH_tasks_G.pTask != 0) && (Index < SCH_MAX_TASKS))
{
Index++;
}
// Have we reached the end of the list?
if (Index == SCH_MAX_TASKS)
{
// Task list is full
//
// Set the global error variable
Error_code_G = ERROR_SCH_TOO_MANY_TASKS;
// Also return an error code
return SCH_MAX_TASKS;
}
// If we're here, there is a space in the task array
SCH_tasks_G.pTask= pFunction;
SCH_tasks_G.Delay= DELAY;
SCH_tasks_G.Period = PERIOD;
SCH_tasks_G.RunMe= 0;
return Index; // return position of task (to allow later deletion)
}
我认为,在创建任务的时候,有必要加入原子保护操作 这本书挺好的 LOVEDZKF 发表于 2014-9-16 15:37
LS正解。。。
正解
。。。
页:
[1]