3 - 任务调度算法 & 同步与互斥 &队列
之前的都是按照优先级不同允许抢占(不讲道理),不管你在做什么,轮到优先级最高的任务,直接抢占执行
怎样才能讲道理呢?稍微等等嘛,等我做完活你再做
1 支持抢占,0不支持抢占
同优先级任务是否交替执行,1交替0不交
空闲任务是否礼让其他任务
礼让的话,自己的函数逻辑在时间片内只执行一遍,然后调度
不支持抢占就行,最好是做完事情后,自觉放弃占用CPU,例:
同步
方案1: 任务A执行完毕后置标志位,任务B时刻检查这个标志位变化,这样实现互斥的话浪费CPU资源,因为两个任务优先级一样,时间片轮转,每次都要进入任务B判断下逻辑;
方案2:使用队列,新创建一个队列,任务A和B各自充当生产者和消费者,生产者运行完毕后生产一个数据放入队列,消费者监控队列,从队列获取到值的时候才执行自己的逻辑. 问:监控队列需要消耗CPU资源么
互斥:两个任务都要使用窗口打印,不等对方打印完,到了自己的时间片就直接抢占打印;
解决办法1:通过判断标志位,后面的延迟是为了让另外一个任务有机会能抢到时间片,不然的话标志位置0后又立马置1,另外的任务永远无法抢到
隐患:当任务多而且执行次数多的时候,就有几率>1个任务同时通过标志位(一个刚好过了if判断,就被切换出去【还没来得及置1】),然后两个任务轮转执行,打破互斥
解决办法2:使用队列, 队列中放一个锁(随便某个数值就行),互斥任务执行的时候需要获取这个锁,就是读取到数值,当队列中没有数值的话就进入阻塞状态,直到抢到这个锁,抢到锁之后可以执行自己的逻辑,执行完毕后再把锁放回到队列中 (距离:互斥使用串口,各自打印各自的数据,完整输出完自己的数据)
可能遇到的问题,只有后面创建的任务使用串口,原因:后面的任务释放了锁(写数据到队列),使阻塞的任务进入就绪态,但是后面的任务仍处于执行态,所以又会获得锁,循环
解决办法: 1.进入等待放弃时间片 2.主动切换任务? 问题: 怎么能保证多个互斥任务都能够有机会执行呢
小技巧: 可以把指针(4字节?)放入到队列中,然后传递指针,这样就可以利用队列传输大量数据(指针指向的地址)
队列的本质是环形buf缓冲区
创建队列,指定队列长度和每个item的大小,开始的时候头尾指针都指向第一个
写一个任务(默认写到尾部),到指针位置,然后PcwriteTo指向下一个item,等待下次写入。 若是写满的话就可以指定其等待时间(阻塞),然后将这个等待任务放到List_t xTasksWaitingToSend队列中; 有位置可以写的话再将其唤醒,【等待时间为0的话,就直接返回报错】
写指针指到最后一位,然后会回到开头(环)
可以使用指定函数写到头部
实际上是写到PcReadFrom指向的位置,然后将其指针-1,下次读的话就先读它,就相当于写数据到头部
若很多任务都在等待,那么有机会的话先唤醒谁呢? 按照优先级和等待时间来判断
常规读
需要指定:读哪个队列?读出的数据放在哪?读不到东西是否等待(等待的话就进等待的队列)
队列初始化的时候PcReadFrom指向最后一个,当开始读的时候,PcReadFrom指针+1(就指向头部)
邮箱:
长度为1的队列,新数据覆盖旧数据,读数据不会移除(橱窗),第一次调用会因为无数据而阻,一旦写入数据,以后读邮箱总能成功
队列集(列集也是队列,之前的队列里面放的是数据,队列集里面放的是队列)
、
准备条件:创建好各自的队列, 然后将各个队列与队列集产生联系,
当按下鼠标的时候,数据会到鼠标的队列中,同时,还会把鼠标的handle放入到队列集中
PS:往队列A中写N个数据,会导致写队列集N次
读队列集,先读出队列,然后从队列中读出数据 (读一次队列,读一次数据)
实际上就是队列的嵌套
8-3 OVER