FREERTOS学习笔记,资源管理一

本文详细介绍了在FREERTOS中如何处理多任务系统中的资源管理问题,包括互斥现象、临界段、挂起调度器、互斥体、优先级翻转和优先级继承等概念,以及如何避免死锁和实现递归互斥体。通过实例展示了如何使用互斥体确保任务间资源的一致性,同时讨论了可能导致的问题及解决方案。
摘要由CSDN通过智能技术生成

介绍

在多任务系统中,若一个任务获取了资源后,在其退出运行状态时并没有释放掉该资源,即使得资源前后状态不一致,则当其他任务或中断调用该资源时会导致数据损坏或其他问题。

实例:

当两个任务试图向LCD屏写东西时。
1,任务A开始执行并向LCD写“HELLO WORLD”,
2,任务A在输出“HELLO W”时忽然被优先级更高的任务B打断。
3,任务B向LCD屏写入 “Abort, Retry, Fail?”然后进入阻塞态。
4,任务A接着执行,向LCD中写入“ORLD”,此时显示屏会显示二者的组合包“HELLO WAbort, Retry, Fail?ORLD”.

读,修改,写操作。

以下面C代码为例:

PORTA |= 0x01;

当编译器编译时会变为下面的汇编语言:

LOAD R1,[#PORTA] ;// Read a value from PORTA into R1

MOVE R2,#0x01 ; //Move the absolute constant 1 into R2

OR R1,R2 ; //Bitwise OR R1 (PORTA) with R2 (constant 1)

STORE R1,[#PORTA] ; //Store the new value back to PORTA

上述过程并不是一个原子过程,因为其执行花费了超过一条指令,并且可以被打断,我们考虑下面一个情形:
1,任务A将PORTA的值加载到寄存器,即汇编代码中第一行。
2,任务B优先级高于A,此时抢占了任务A。
3,任务B更新了PORTA中的值,然后进入阻塞态。
4,任务A接着执行,但其修改的只是原来的值,然后将原来的值修改后放入PORTA中,B更新的值完全被忽略。

非原子方式处理变量
当一个16位单片机处理32位变量时,当读取32位变量中16位后,被其他任务抢占,最终很容易导致数据损坏或丢失。

函数重进入

函数可以重进入表明当多个任务调用该函数时,它是线程安全的。重进入函数被称为线程安全的原因是当多个任务调用该函数时,并不会发生数据损坏或丢失等问题。
每一个任务都有独立的栈与独立的寄存器的值,若一个函数并不会对任务中的栈或寄存器的值直接操作,则该函数可以称做为重进入函数,即是线程安全的。
下面的代码为一个线程安全函数:

/* A parameter is passed into the function. This will either be passed on the stack,
or in a processor register. Either way is safe as each task or interrupt that calls
the function maintains its own stack and its own set of register values, so each task
or interrupt that calls the function will have its own copy of lVar1. */
long lAddOneHundred( long lVar1 )
{
   
	/* This function scope variable will also be allocated to the stack or a register,
	depending on the compiler and optimization level. Each task or interrupt that calls
	this function will have its own copy of lVar2. */
	long lVar2;
	lVar2 = lVar1 + 100;
	return lVar2;
}

下面的为线程不安全的函数:

/* In this case lVar1 is a global variable, so every task that calls
lNonsenseFunction will access the same single copy of the variable. */
long lVar1;
long lNonsenseFunction( void )
{
   
	/* lState is static, so is not allocated on the stack. Each task that calls this
	function will access the same single copy of the variable. */
	static long lState = 0;
	long lReturn;
	switch( lState )
	{
   
		case 0 : lReturn = lVar1 + 10;
				lState = 1;
				break;
		case 1 : lReturn = lVar1 + 20;
				lState = 0;
		break;
	}
}

互斥现象

为了确保任务与任务间或任务与中断间共享的数据在任意时刻都保持一致性,故采用互斥(‘mutual exclusion’)的方法。目的是为了确保,一旦一个任务开始获取一个共享的但非重进入和非线程安全的资源,则其他相关的任务必须等待该任务将正确资源返回后才可使用该资源。

临界段和挂起调度器

基础临界段
基础临界段就是一个被宏taskENTER_CRITICAL() 和 taskEXIT_CRITICAL()包围的代

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值