完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
测试前准备: 1、串口一个,当做可被抢占的资源。 2、准备好三个用户任务,设置优先级为高、中、低(具体值自己设置,比如5、10、15),按照优先级命名函数。 3、创建一个信号量。 创建信号量的代码: OS_EVENT *testsem; testsem = OSSemCreate(1); 任务代码分别为: void TaskHigh(void *p_arg) { u8 err; while(1) { OSSemPend(testsem, 0, &err); //申请(等待)信号量 printf("%c",'T');delay_ms(10);printf("%c",'a');delay_ms(10); printf("%c",'s');delay_ms(10);printf("%c",'k');delay_ms(10); printf("%c",'H');delay_ms(10);printf("%c",'i');delay_ms(10); printf("%c",'g');delay_ms(10);printf("%c",'h');delay_ms(10); printf("%c",' ');delay_ms(10);printf("%c",'g');delay_ms(10); printf("%c",'e');delay_ms(10);printf("%c",'t');delay_ms(10); printf("%c",' ');delay_ms(10);printf("%c",'t');delay_ms(10); printf("%c",'h');delay_ms(10);printf("%c",'e');delay_ms(10); printf("%c",' ');delay_ms(10);printf("%c",'c');delay_ms(10); printf("%c",'o');delay_ms(10); printf("%c",'m');printf("%c",'r');printf("%c",'n'); OSSemPost(testsem); OSTimeDly(1); } } void TaskMedium(void *pdata) { while(1) { printf("_rn"); OSTimeDly(10); } } void TaskLow(void *p_arg) { u8 err; while(1) { OSSemPend(testsem, 0, &err); //申请(等待)信号量,不设置超时。 printf("%c",'T');delay_ms(10);printf("%c",'a');delay_ms(10); printf("%c",'s');delay_ms(10);printf("%c",'k');delay_ms(10); printf("%c",'L');delay_ms(10);printf("%c",'o');delay_ms(10); printf("%c",'w');delay_ms(10);printf("%c",' ');delay_ms(10); printf("%c",'g');delay_ms(10);printf("%c",'e');delay_ms(10); printf("%c",'t');delay_ms(10);printf("%c",' ');delay_ms(10); printf("%c",'t');delay_ms(10);printf("%c",'h');delay_ms(10); printf("%c",'e');delay_ms(10);printf("%c",' ');delay_ms(10); printf("%c",'c');delay_ms(10);printf("%c",'o');delay_ms(10); printf("%c",'m');printf("%c",'r');printf("%c",'n'); OSSemPost(testsem); //释放信号量 OSTimeDly(1); } } 说明一下这么设计的意图,为了更好观察相关的现象,选择串口作为公共资源比设置一个变量数组更加直观,被抢占后能直接打印当前任务的字符串。代码中使用了阻塞延时是为了延迟任务的执行速度,另一个角度说就是能更明显的看到被抢占的现象。
直接进入正题。
运行效果如下: 红圈多出来的一个字符就是TaskLow任务需要打印的字符串。由此可知TaskLow任务在使用串口时,被优先级高的TaskHigh给抢去了。如果不想被抢走就需要用到信号量。
运行效果如下: 使用信号量后, TaskLow任务能完整打印字符串,说明在使用串口时不会被抢走了。 需要注意的是信号量可以分为二值信号量和计数信号量。计数信号量可根据资源数量设置信号量的数量,举个栗子比如银行业务窗口只能同时有5个人办理业务,再多的就要排队,这时就设置信号量数量为5,来一个人办理信号量就减一,减到0时说明人满了,其他人就要排队。当有人办理完时,信号量就加一,队伍里的人就可以出来一个去办理,这时信号量又减一,以此类推。计数信号量目前我还没使用过,不多讨论。 而二值信号量,数量只有1(0和1两个值),其中一个功能就是互斥。什么叫互斥,就是你用了我就不能用,我用了你就不能用,上面例程中使用的就是二值信号量,体现了互斥功能。二值信号量还有个功能就是同步,简单说就是当做一个标志量来使用,即一个地方只释放信号量,另一个地方等到信号量后就能执行。
运行结果如下: 小横杠是TaskMedium任务打印的字符串,可以看到TaskLow任务不停被打断。 这么看可能看不出什么名堂,低优先级被高优先级打断不是很正常吗?哪里能看到优先级翻转了呢?结合下图继续往下看。 有时候,低优先级的任务在占着资源未释放信号量,高优先级的任务也要用资源的话就得等待(比如TaskLow任务正在占用串口打印字符串,TaskHigh任务在等待),这时候有个中优先级的任务需要需要运行(比如TaskMedium任务过来打印小横杠)。因为TaskHigh优先级高,按理说TaskHigh任务只是在等待CPU使用权(使用了OSTimeDly()之类叫主动释放,这时谁要用CPU都不关心了),并不允许其他任务(优先级比TaskHigh低的)比它先得到使用权。就像排队,下一个就到我了,不许有人插队进来。 但实际就偏有人插队进来。如运行效果,TaskLow任务不断被打扰,但由于还未释放信号量,TaskHigh任务是没法获得CPU使用权来运行的,只能干瞪眼看着可恶的TaskMedium任务在捣乱,这看起来是TaskMedium优先级比TaskHigh高了,这就是优先级翻转现象。TaskMedium任务捣乱会让TaskLow任务不能尽快完成,TaskHigh任务就需要花更多时间等待。如果TaskMedium任务本身就需要很多时间来运行,TaskHigh任务将等到天荒地老,这对于实时操作系统是个灾难。 这里需要说明一下,TaskMedium任务不通过信号量使用了同一个串口,原则上违背了例程“使用信号量达到资源独占”的目的,但为了能体现优先级反转现象才这么设计,TaskMedium可以不用串口,去做别的事,但依旧会因优先级高于TaskLow而打断TaskLow。
创建互斥信号量的代码: OS_EVENT *testmutex;testmutex = OSMutexCreate(MUTEX_PRIO, &err); //MUTEX_PRIO是占用互斥信号量的任务被提升时所需的优先级 运行结果如下: 可以看到TaskLow任务已经能完整打印字符串。 互斥信号量能解决优先级翻转问题的关键在于,把占用信号量任务的优先级给提高了。TaskLow任务在占用信号量期间,优先级会被提升,这样就不会被打断以便尽快运行完释放信号量,释放信号量后TaskLow任务优先级会恢复到原来的。 使用互斥信号量需要注意一些地方。 官方明确规定,任务占用互斥信号量期间(还未释放信号量),不能挂起该任务,也就是不能使用延时之类的将任务挂起。否则这互斥信号量就失效了。 对于提升优先级到底需要提升到多少,这个根据情况而定了,一般比所有等待互斥信号量的任务高一级就行,比如TaskHigh 优先级5,可以把TaskLow优先级提升至4。 还有优先级天花板的问题,即等待互斥信号的任务是最高了(0级),占用信号量的任务还能不能提升?此问题网上也有很多讨论,这里不多赘述。 |
|
|
|
只有小组成员才能发言,加入小组>>
3314 浏览 9 评论
2995 浏览 16 评论
3494 浏览 1 评论
9059 浏览 16 评论
4088 浏览 18 评论
1178浏览 3评论
605浏览 2评论
const uint16_t Tab[10]={0}; const uint16_t *p; p = Tab;//报错是怎么回事?
599浏览 2评论
用NUC131单片机UART3作为打印口,但printf没有输出东西是什么原因?
2335浏览 2评论
NUC980DK61YC启动随机性出现Err-DDR是为什么?
1896浏览 2评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-23 05:53 , Processed in 1.091649 second(s), Total 47, Slave 38 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号