【UCOSIII】【普通信号量】访问共享资源、任务同步;【任务内嵌信号量】任务同步;【互斥信号量】防止优先级反转;

一、信号量实现 访问共享资源

task4 task5共同需要访问共享资源区,都同时请求信号量

其中一个在访问的时候,另一个只能处于等待状态。

//task4、5:使用信号量访问共享资源区
void task4_task(void *p_arg)
{
	OS_ERR err;
	u8 str1[] = "task4 using share_resource";
	while(1)
	{
		OSSemPend(&SEM_share_resource,0,OS_OPT_PEND_BLOCKING,0,&err);	//等待信号量 请求
		memcpy(share_resource,str1,sizeof(str1));
		printf("%s\r\n",share_resource);
		OSSemPost(&SEM_share_resource,OS_OPT_POST_1,&err);	//发送信号量 释放
		
		printf("task4_......\r\n");
	}
}

void task5_task(void *p_arg)
{
	OS_ERR err;
	u8 str2[] = "task5 using share_resource";
	while(1)
	{
		OSSemPend(&SEM_share_resource,0,OS_OPT_PEND_BLOCKING,0,&err); //等待信号量 请求
		memcpy(share_resource,str2,sizeof(str2));
		printf("%s\r\n",share_resource);
		OSTimeDlyHMSM(0,0,5,0,OS_OPT_TIME_PERIODIC,&err);		//延时5s,释放对cpu的控制权
		OSSemPost(&SEM_share_resource,OS_OPT_POST_1,&err);	//发送信号量 释放
	
	}

}

二、信号量                实现 任务同步

五、任务内嵌信号量  实现 任务同步

task6 按按键‘上’,实现post信号量,即信号量+1

task7不停地请求一次信号量,如果请求到 OSTimedly 1s后再请求。

OS_SEM	 SEM_1;		   //普通信号量

OS_TCB	Task7_TaskTCB;     //任务内嵌信号量    不用声明 结构体  TCB结构体有

//普通信号量
OSSemCreate((OS_SEM      *)&SEM_1,		
	    (CPU_CHAR    *)"SEM_1",   
            (OS_SEM_CTR   )1,   					//初始化 信号量 值为0
	    (OS_ERR      *)&err	);  

//任务内嵌信号量 
不用创建 信号量,TCB块中已经有了,直接调用
OS_TCB	Task7_TaskTCB;    
Task7_TaskTCB.SemCtr       //代表任务内嵌信号量的值
//普通信号量        请求、释放
OSSemPend(&SEM_task_synchronous,0,OS_OPT_PEND_BLOCKING,0,&err);	//等待信号量 请求
OSSemPost(&SEM_task_synchronous,OS_OPT_POST_1,&err); //发送信号量 释放 信号量+1

//任务内嵌信号量    请求、释放
OSTaskSemPend((OS_TICK   )0,				//请求系统内部信号量 1s请求一次 Task7_TaskTCB.SemCtr
              (OS_OPT    )OS_OPT_PEND_BLOCKING,
              (CPU_TS   *)0,
              (OS_ERR   *)&err);
OSTaskSemPost((OS_TCB   *)&Task7_TaskTCB,		//释放系统内部信号量 Task7_TaskTCB.SemCtr
	        (OS_OPT    )OS_OPT_POST_NONE,
		(OS_ERR   *)&err);
//task6、7:使用信号量实现任务同步
void task6_task(void *p_arg)
{
	OS_ERR err;
	u8 key;
	while(1)
	{
		key = KEY_Scan(0);
		switch(key)
		{
			case WKUP_PRES:
				
//普通信号量sem:1  系统内部信号量tasksem:0
#define SEM_or_Tasksem 0
#if SEM_or_Tasksem
				OSSemPost(&SEM_task_synchronous,OS_OPT_POST_1,&err); //发送信号量 释放 信号量+1
				printf("task6 Sem post = %d \r\n",SEM_task_synchronous.Ctr);
				break;
#else
				OSTaskSemPost((OS_TCB   *)&Task7_TaskTCB,		//释放系统内部信号量 Task7_TaskTCB.SemCtr
							  (OS_OPT    )OS_OPT_POST_NONE,
							  (OS_ERR   *)&err);
				printf("task6 TaskSem post = %d \r\n",Task7_TaskTCB.SemCtr);
				break;
#endif			

		}
		OSTimeDlyHMSM(0,0,0,10,OS_OPT_TIME_PERIODIC,&err);		//延时5s,释放对cpu的控制权

	}
}

void task7_task(void *p_arg)
{
	OS_ERR err;
	while(1)
	{

		OSTimeDlyHMSM(0,0,5,0,OS_OPT_TIME_PERIODIC,&err);		//延时5s,释放对cpu的控制权
#if SEM_or_Tasksem
		OSSemPend(&SEM_task_synchronous,0,OS_OPT_PEND_BLOCKING,0,&err);	//等待信号量 请求
		printf("task7 Sem pend = %d \r\n",SEM_task_synchronous.Ctr);
#else
		OSTaskSemPend((OS_TICK   )0,						//请求系统内部信号量 1s请求一次 Task7_TaskTCB.SemCtr
                      (OS_OPT    )OS_OPT_PEND_BLOCKING,
                      (CPU_TS   *)0,
                      (OS_ERR   *)&err);
		printf("task7 Sem pend = %d \r\n",Task7_TaskTCB.SemCtr);
#endif

		LED0 = ~LED0;
		OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_PERIODIC,&err);//防止灯闪的太快 看不清
	}

}

三、普通信号量OS_SEM    ——会出现 优先级反转 的情况

四、互斥信号量OS_MUTEX——防止优先级反转

场景:高优先级、低优先级共同访问一个信号量,中优先级不访问信号量

当一个低优先级任务和一个高优先级任务同时使用同一个信号量,而系统中还有其他中等优先级任务时。

如果低优先级任务获得了信号量,那么高优先级的任务就会处于等待状态,

但是,中等优先级的任务可以打断低优先级任务而先于高优先级任务运行

(此时高优先级的任务在等待信号量 ,所以不能运行),

这时就出现了优先级反转的现象。

//0:mutex  1:sem  
#define mutex_or_sem 0

OS_SEM	 SEM_1;			//普通信号量,会出现优先级反转现象
OS_MUTEX MUTEX_1;		//互斥信号量,防止优先级反转
//优先级反转实验					   
//普通信号量
OSSemCreate((OS_SEM      *)&SEM_1,		
	(CPU_CHAR    *)"SEM_1",   
	(OS_SEM_CTR   )1,   		//初始化 信号量 值为1
	(OS_ERR      *)&err	);   				   			   
//创建互斥信号量
OSMutexCreate((OS_MUTEX  *)&MUTEX_1,
	    (CPU_CHAR  *)"MUTEX_1",
	    (OS_ERR    *)&err);				  
//互斥信号量 防止优先级反转
void task8_task(void *p_arg)
{
	OS_ERR err;
	while(1)
	{
		printf("high task pend sem...\r\n");
//0:mutex  1:sem  
#define mutex_or_sem 0

#if mutex_or_sem		
		OSSemPend(&SEM_1,0,OS_OPT_PEND_BLOCKING,0,&err);	//等待信号量 请求
#else
		OSMutexPend((OS_MUTEX  *)&MUTEX_1,		//请求互斥信号量
                   (OS_TICK    )0,
                   (OS_OPT     )OS_OPT_PEND_BLOCKING,
                   (CPU_TS    *)0,
                   (OS_ERR    *)&err);		
#endif
		printf("high task running\r\n");
		
#if mutex_or_sem		
		OSSemPost(&SEM_1,OS_OPT_POST_1,&err); //发送信号量 释放 信号量+1
#else
		OSMutexPost((OS_MUTEX  *)&MUTEX_1,		//释放互斥信号量
                   (OS_OPT     )OS_OPT_POST_NONE,
                   (OS_ERR    *)&err);
#endif
		printf("high task post sem\r\n");
		OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_PERIODIC,&err);//1s延迟
	}

}
void task9_task(void *p_arg)
{
	OS_ERR err;
	while(1)
	{
		printf("middle task running\r\n");
		OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_PERIODIC,&err);//1s延迟
	}

}
void task10_task(void *p_arg)
{
	OS_ERR err;
	int i;
	while(1)
	{
		printf("low task pend sem...\r\n");
#if mutex_or_sem
		OSSemPend(&SEM_1,0,OS_OPT_PEND_BLOCKING,0,&err);	//等待信号量 请求
#else
		OSMutexPend((OS_MUTEX  *)&MUTEX_1,		//请求互斥信号量
                   (OS_TICK    )0,
                   (OS_OPT     )OS_OPT_PEND_BLOCKING,
                   (CPU_TS    *)0,
                   (OS_ERR    *)&err);		
#endif
		printf("low task running\r\n\r\n");
		
		for(i=0;i<5000000;i++)
			OSSched();	//任务级调度
#if mutex_or_sem
		OSSemPost(&SEM_1,OS_OPT_POST_1,&err); //发送信号量 释放 信号量+1
#else
		OSMutexPost((OS_MUTEX  *)&MUTEX_1,		//释放互斥信号量
                   (OS_OPT     )OS_OPT_POST_NONE,
                   (OS_ERR    *)&err);
#endif

	}

}

普通信号量:

优先级反转结果:middle优先于high运行

high task pend sem...
middle task running
middle task running
middle task running
middle task running

high task running
high task post sem
low task pend sem...
low task running

互斥信号量:

防止优先级反转结果:

high请求互斥信号量未果,low使用互斥信号量中,low优先级提升为high级别

middle等待 low释放互斥信号量 优先级恢复,然后high获得互斥信号量的请求,并释放请求,才能执行middle

high task pend sem...

high task running
high task post sem
middle task running
low task pend sem...
low task running


猜你喜欢

转载自blog.csdn.net/qq1518572311/article/details/80527103