深圳做微商网站,做网站租用那个服务器好,部队网站建设招标,WordPress不收录首页文章目录 为什么需要互斥访问#xff1f;使用队列实现互斥访问休眠和唤醒机制环形缓冲区 为什么需要互斥访问#xff1f;
在裸机中#xff0c;假设有两个函数#xff08;func_A, func_B#xff09;都要修改a的值#xff08;a#xff09;#xff0c;那么将a定义为全局变… 文章目录 为什么需要互斥访问使用队列实现互斥访问休眠和唤醒机制环形缓冲区 为什么需要互斥访问
在裸机中假设有两个函数func_A, func_B都要修改a的值a那么将a定义为全局变量a0main函数调用func_A();func_B(); 此时a的值为2。因为不存在多任务执行代码是按照顺序执行的。
在多任务系统中多个任务在微观上是串行执行宏观上是并行执行的。 假设两个任务func_A, func_B也都要修改a的值a会有什么情况呢 首先将修改a的值的代码a做个拆分 1、从内存中将a的值读到寄存器R0中 2、修改寄存器R0的值 3、将寄存器R0的值写回内存a中。
第一个时间片段执行 func_A执行完第一步从内存中将a的值读到寄存器R0中aR00任务切换要释放CPU使用权。任务切换之前会将现场保存下来 R00 第二个时间片段执行 func_B期间将3个步骤都执行完aR00R0R01011; R0a1后任务切换要释放CPU使用权。 第三个时间片段func_A接着执行之前先将现场恢复R00执行后面两个步骤R0R01011; R0a1 通过上面的两个任务细分执行的过程会发现当多个任务共用操作一个变量时会发生异常。为了避免这种异常引入互斥访问变量的方式。
使用队列实现互斥访问 当有多个任务操作变a时为了确保每个任务操作a期间不被其他任务所影响就调用队列来做隔离任务B要去读a的值时直接调用队列处理好的数据即可。 队列的任务1、关闭中断2、环形缓冲区操作a的值3、链表操作4、打开中断
当任务A调用队列关闭中断后其他任务不会再被调度执行相当于逻辑程序操作完变量a之后打开中断此时恢复CPU调度机制。使用队列可以实现互斥访问避免多个任务同时操作一个变量时造成的异常现象。
RTOS中 调度队列函数接口 写队列xQueueSend读队列xQueueReceive
休眠和唤醒机制
任务在读队列的时候会出现两种情况 第一种情况、读到队列中的值返回 第二种情况、队列读不到值将任务休眠
场景只有两个任务A和任务B读写a的值 第一个时间片段任务A 运行在这个时间段中还没有调用队列修改a的值 第二个时间片段任务B运行读队列没有得到a的值将任务B休眠 第三个时间片段 —— 第五个时间片段由于任务B处于休眠状态因此任务A全速运行 第六个时间片段任务A 写队列修改a的 值并唤醒任务B 第七个时间片段任务B 继续执行。 因此使用队列的方式不仅能实现互斥访问还能使用休眠和唤醒机制让CPU更高效的运行。 注唤醒任务B任务B是不会马上执行要等到下一个tick中断
写队列的动作1、修改 Data值2、唤醒任务wake up 怎么知道唤醒哪个任务呢队列链表Queue.list将需要唤醒的任务放在链表里。
读队列的动作1、有Data值返回2、无Data休眠 休眠1、将任务从ReadyList移动到DelayList2、将任务记录到Queue.list队列链表。
环形缓冲区 缓冲区本质上就是数组假设这个缓冲区的长度为8写缓冲区指针w刚开始在0的位置每写一个val指针w位置1%8以此类推最后的w8%8。这样就形成闭环也就是环形缓冲区。读操作也是一样的
由于链表的大小是有限的所以当任务写缓冲区的时候发现已经写满了就会将任务放到Queue.list队列链表中的list for send 链表中 在任务在读缓冲区的值时没有读出来会将任务放到Queue.list队列链表中的list for receive 链表中