互斥型信号量
来源:互联网 发布:sql安装参数错误 编辑:程序博客网 时间:2024/05/24 01:28
在任哲的书本《嵌入式实时操作系统uc/osII原理与应用》第五章所描述的,互斥型信号量将占用共享资源的任务提升到当前最高的优先级,使其能够完整的执行完毕,然后再恢复原先的优先级;这样避免了仅仅使用信号量而出现优先级反转的现象,(当然互斥型信号量就是出于这个目的设计的吧)。
所以在书里的程序里面设计了这样三个任务。优先级为6的任务MyTask、优先级为7的任务YouTask,和优先级为8的HerTask。
HerTask一开始占用了优先级为3的互斥信号量Semp,并且占用时间比较长。
/*****利用互斥信号量消除了优先级反转的现象**************/#include "includes.h"#define TASK_STK_SIZE 512 //任务堆栈长度OS_STK MyTaskStk[TASK_STK_SIZE]; //定义任务堆栈区OS_STK YouTaskStk[TASK_STK_SIZE]; //定义任务堆栈区OS_STK HerTaskStk[TASK_STK_SIZE]; //定义任务堆栈区OS_STK StartTaskStk[TASK_STK_SIZE];//char *s1="MyTask running";char *s2="YouTask running";char *s3="HerTask running";char *ss="MyTask pend_semp";INT8U err;INT8U y=0;INT32U Times=0;INT16S key; //用于退出uCOS_II的键OS_EVENT *Semp; //声明事件控制块void MyTask(void *pdata); //声明任务void YouTask(void *pdata); //声明任务void HerTask(void *pdata); //声明任务void StartTask(void *pdata);void QuitKey(void);/***************主函数*****************/void main (void){ OSInit(); //初始化uCOS_II PC_DOSSaveReturn( ); //保存Dos环境 PC_VectSet(uCOS, OSCtxSw); //安装uCOS_II中断 Semp=OSMutexCreate(3,&err); //定义信号量 OSTaskCreate(StartTask, //创建任务MyTask (void*)0, //给任务传递参数 &StartTaskStk[TASK_STK_SIZE - 1], //设置任务堆栈栈顶指针 5); //使任务的优先级别为5 OSStart(); //启动多任务管理}/*************任务StartTask***************/void StartTask (void *pdata){ pdata = pdata; OS_ENTER_CRITICAL(); PC_VectSet(0x08, OSTickISR); //安装时钟中断向量 PC_SetTickRate(OS_TICKS_PER_SEC); //设置uCOS_II时钟频率 OS_EXIT_CRITICAL(); OSStatInit( ); //初始化统计任务 OSTaskCreate(MyTask, //创建任务YouTask 0, //给任务传递参数 &MyTaskStk[TASK_STK_SIZE - 1], //设置任务堆栈栈顶指针 6); //使任务的优先级别为6 OSTaskCreate(YouTask, //创建任务YouTask 0, //给任务传递参数 &YouTaskStk[TASK_STK_SIZE - 1], //设置任务堆栈栈顶指针 7); //使任务的优先级别为7 OSTaskCreate(HerTask, //创建任务YouTask 0, //给任务传递参数 &HerTaskStk[TASK_STK_SIZE - 1], //设置任务堆栈栈顶指针 8); OSTaskSuspend(OS_PRIO_SELF); //把StartTask给挂起来了}/******任务MyTask**********/void MyTask (void *pdata){ pdata = pdata; for (;;) { OSTimeDlyHMSM(0,0,0,200); { PC_DispStr(10,++y,ss,DISP_BGND_BLACK+DISP_FGND_WHITE); OSMutexPend(Semp,0,&err); PC_DispStr(10,++y,s1,DISP_BGND_BLACK+DISP_FGND_WHITE); OSMutexPost(Semp);//发送信号量 QuitKey(); } OSTimeDlyHMSM(0,0,0,200); }}/************任务YouTask*************/void YouTask (void *pdata){ pdata = pdata; for (;;) { PC_DispStr(10,++y,s2,DISP_BGND_BLACK+DISP_FGND_WHITE); QuitKey(); OSTimeDlyHMSM(0,0,0,300); //等待300ms }}/************任务HerTaskk*******************/void HerTask (void *pdata){ pdata = pdata; for (;;) { OSMutexPend(Semp,0,&err);//请求信号量 PC_DispStr(10,++y,s3,DISP_BGND_BLACK+DISP_FGND_WHITE);//显示s3,表示请求成功 for(Times=0;Times<40000000;Times++) {OS_Sched();} OSMutexPost(Semp);//占用较长的时间,这里才释放互斥型信号量 QuitKey(); OSTimeDlyHMSM(0,0,1,0); }}/*******************按键退出************************/void QuitKey(void){ //如果按下Esc键则退出uCOS_II if (PC_GetKey(&key) == TRUE) { if (key == 0x1B) { PC_DOSReturn( );//恢复DOS环境 } }}
运行结果:
看运行结果,先出现MyTask后出现YouTask ,正如我们所期望的,消除了优先级反转。
但是,出于好奇,我在HerTask任务里面加了一句。如下面代码所示。
for (;;) { OSMutexPend(Semp,0,&err); PC_DispStr(10,++y,s3 ,DISP_BGND_BLACK+DISP_FGND_WHITE); for(Times=0;Times<40000000;Times++) {OS_Sched();} OSMutexPost(Semp);//加了下面这一句,通过显示HerTask over来确认HerTask什么时候释放了信号量 PC_DispStr(10,++y,"HerTask over", DISP_BGND_BLACK+DISP_FGND_WHITE); QuitKey(); OSTimeDlyHMSM(0,0,1,0); }
而运行结果让我惊讶。
乍一看,怎么HerTask没有释放信号量,MyTask就已经得到互斥信号量并且运行了呢,YouTask也运行了。这不是和理论相违背吗。按照常理,不是应该HerTask先释放信号量,然后MyTask才能请求,运行吗?
先别忙着质疑理论,为了弄清楚哪里出错了,我又在HerTask释放信号量的语句前,加了一句显示的语句,
for (;;) { OSMutexPend(Semp,0,&err); PC_DispStr(10,++y,s3,DISP_BGND_BLACK+DISP_FGND_WHITE); for(Times=0;Times<40000000;Times++) {OS_Sched();} //这一次在释放前加了一句显示HerTask over1 PC_DispStr(10,++y,"HerTask over1", DISP_BGND_BLACK+DISP_FGND_WHITE); OSMutexPost(Semp); PC_DispStr(10,++y,"HerTask over", DISP_BGND_BLACK+DISP_FGND_WHITE); QuitKey(); OSTimeDlyHMSM(0,0,1,0); }
结果如下:
说明MyTask获得信号量是在HerTask任务的语句:for(Times=0;Times<40000000;Times++){OS_Sched();}之后才获得信号量的,准确来说是在显示了字符串”HerTask over1”之后才获得信号量的。
所以,只能说明在显示完”HerTask over1”之后,任务进行了切换,而且切换发生在了显示”HerTask over”之前,那么也就是说在OSMutexPost()函数里面肯定进行了切换。这是唯一的可能了,因为没有设置中断切换,那么要从HerTask转到MyTask执行,就只剩下任务级切换了。所以我查了一下OSMutexPost()函数的定义,发现函数里面确实调用了OSched()进行了任务的切换,所以说此次切换就是使得MyTask得以执行。所以以上的疑问也就解开了。
以上就是我对于互斥型信号量的一些理解,不妥之处欢迎指正。
- 互斥型信号量
- 信号量
- 信号量
- 信号量
- 信号量
- 信号量
- 信号量
- 信号量
- 信号量
- 信号量
- 信号量
- 信号量
- 信号量
- 信号量
- 信号量
- 信号量
- <>信号量
- 信号量
- java 用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。
- 羽毛球比赛中羽毛球擦网和卡网(挂网)怎么判罚?
- javascript正则表达式用法 (test|match|search|replace|split|exec)
- 2016.6.20
- Git版本管理使用教程
- 互斥型信号量
- 多线程编程(一)多线程基础
- Git的使用
- iOS 判断字符串中含有某个字符串
- maven详解六、maven的使用问答
- 纯虚函数简单示例
- windows 上安装2个mysql 无法启动错误处理
- Handler相关
- 【JAVA学习】Core Java读书记录