FreeRTOS - 资源

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/tq384998430/article/details/87938957

这里所说的资源并不仅仅指CPU和内存,打印机、显示器、音响等都算是资源。只要是资源,就存在占用问题,例如如果有两个任务A、B在同一个时间段都想使用同一台打印机进行打印服务,如果系统不对A和B进行管理,两个任务同时向打印机发送数据,可能就会出现冲撞导致打印错误,如果系统先让A任务打印,然后再让B打印,这样就避免了任务之间的资源占用冲撞问题。

这里需要介绍一个概念:原子操作,这个概念应用在某个操作上表示该操作是无法拆分的,是原子级别的,例如:

GlobalVar |= 0x01;

上面这段程序就不属于原子操作,因为这段程序编译成汇编程序之后就成下面:

LDR r4,[pc,#284]
LDR r0,[r4,#0x08] /* Load the value of GlobalVar into r0. */
ORR r0,r0,#0x01 /* Set bit 0 of r0. */
STR r0,[r4,#0x08] /* Write the new r0 value back to GlobalVar. */

简简单单的一端C语言翻译成汇编就有4行,是一个典型的Read、Modify、Write操作,4行代码的执行过程可能会被打断,例如当执行完前两行的Read操作之后发生任务调度,在另一个任务中对GlobalVar 变量进行了一次赋值,当再次返回到这个任务的时候GlobalVar 的值其实已经改变了,这时候在执行下面的Modify和Write操作就会出现数据错误的情况。

为了解决上面的问题,我们可以使用临界区、关闭任务调度器、互斥锁三种方式。

临界区可以使用类似 ENTER_CRITICAL() 函数/宏进入,使用 EXIT_CRITICAL() 退出临界区域,一般ENTER_CRITICAL是关闭总中断,EXIT_CRITICAL是打开总中断,这样一来在临界区域中执行代买就不会被中断事件打断,也就是不会出现上面例子中执行完Read操作就被高优先级的任务打断的情况。但是这种做法的缺点也是很明显的,关闭了总中断就会影响其他非常重要的事件的处理,即使这个非常重要的事件并没有与这个当前有资源争夺的情况,这时候互斥锁可以很好的解决这个问题。

关闭任务调度器可以防止系统发生任务调度,这种方式可以保证受保护区域的代码不会被其他任务所打断,但是不同意临界区,关闭任务调度器任然允许产生中断,这时候如果中断ISR和任务存在资源争夺的话也会导致错误。

互斥锁的原理:当资源被锁住的时候,资源就处于不可访问的状态,当资源处于解锁状态的时候,资源才可以被访问。这样假设A任务和B任务竞争一个资源C,A在访问C的时候会先查看C的锁是否处于锁住状态,如果处于锁住状态则进入Blocked状态,否则则占用C并将C的互斥锁锁住,这时候假如B任务抢占CPU,也对C进行访问,但是发现C的互斥锁处于锁住的状态,那么B就会进入Blocked状态,等到A使用完C之后会释放C的互斥锁,这才会将B任务从Blocked状态唤醒。

猜你喜欢

转载自blog.csdn.net/tq384998430/article/details/87938957
今日推荐