个人技术分享

信号量的使用


前言

队列就像一个传送带,可以传送不同数据。信号量不能传输数据,只能表示资源的数量,信号量只有一个计数值。在前面同步互斥中,我们有两个实验。

同步实验: 我们创建了两个任务,任务1循环遍历一个比较大的数字,遍历完成后设置标志位置1。任务2等待任务1标志位置1后串口发送数据,但是在任务2等待过程中也参与CPU的调度,从而导致任务1计算时间增加。
我们的问题就是既然任务2在等待,那如何配置才能让任务2不抢占CPU资源。

互斥实验: 两个任务交替使用一个函数发送串口数据。

上一章我们用队列解决同步互斥,但由于队列数据保存也需要空间。本章我们使用信号量来解决。使用信号量时不需要传递数据和复制数据,更节省空间、效率更高


一、计数型信号量使用

创建句柄

static SemaphoreHandle_t xSemCalc;
	xSemCalc = xSemaphoreCreateCounting(10, 0);

释放信号和获取信号

void Task1Function(void * param)
{
	volatile int i = 0;
	while (1)
	{
		for (i = 0; i < 10000000; i++)
			sum++;
		//printf("1");
		xSemaphoreGive(xSemCalc);
		vTaskDelete(NULL);
	}
}

void Task2Function(void * param)
{
	while (1)
	{
		//if (flagCalcEnd)
		flagCalcEnd = 0;
		printf("flagCalcEnd = %d\r\n", flagCalcEnd);
		xSemaphoreTake(xSemCalc, portMAX_DELAY);
		flagCalcEnd = 1;
		printf("sum = %d\r\n", sum);
	}
}

二、二进制信号量实现互斥

创建句柄

static SemaphoreHandle_t xSemUART;
	xSemUART = xSemaphoreCreateBinary();
	xSemaphoreGive(xSemUART);//初始值设为1表示可以使用

释放信号和获取信号

void TaskGenericFunction(void * param)
{
	while (1)
	{
		xSemaphoreTake(xSemUART, portMAX_DELAY);
		printf("%s\r\n", (char *)param);
		xSemaphoreGive(xSemUART);
		vTaskDelay(1);
	}
}