1.总结二进制信号量和计数型信号量的区别,以及他们的使用场景。
区别:
二进制信号量:信号量的数值只有0和1。
计数型信号量:计数型信号量的值一般访问是大于或者等于2。
使用场景:
(1)二进制信号量
互斥访问共享资源:当多个进程或线程需要互斥地访问共享资源时,可以使用二进制信号量来保证只有一个进程能夈访问资源。
同步进程执行:用于控制进程的执行顺序,确保在某些情况下只有特定进程能夈执行。
(2)计数型信号量
控制资源的数量:当需要限制某种资源的数量时,可以使用计数型信号量来管理资源的分配和释放。
生产者-消费者问题:用于解决生产者和消费者之间的同步和互斥问题,其中计数型信号量可以表示缓冲区中的可用空间或数据项数量。
2.使用计数型信号量完成生产者和消费者模型实验。
//自动创建的计数信号量
myCountingSem01Handle = osSemaphoreNew(2, 2, &myCountingSem01_attributes);
const osSemaphoreAttr_t myCountingSem01_attributes = {
.name = "myCountingSem01"
};
#define BUFFER_SIZE 5 //消息队列的大小
#define NUM_PRODUCERS 2 //生产者
#define NUM_CONSUMERS 2 // 消费者
//创建了一个消息队列 bufferHandle
osMessageQueueId_t bufferHandle;
//消费者任务通过从消息队列中获取数据来模拟消费
//生产者
void StartDefaultTask(void *argument) {
int item = 0;
while (1) {
osDelay(1000); =
if (osSemaphoreAcquire(myCountingSem01Handle, osWaitForever) == osOK) {
osMessageQueuePut(bufferHandle, &item, 0, osWaitForever);
item++;
osSemaphoreRelease(myCountingSem01Handle);
}
}
}
//消费者
void StartTask02(void *argument) {
int item;
while (1) {
if (osMessageQueueGet(bufferHandle, &item, NULL, osWaitForever) == osOK) {
// Consume item
osDelay(500); // Simulate consumption time
}
}
}
int main(void) {
myCountingSem01Handle = osSemaphoreNew(2, 2, &myCountingSem01_attributes);
bufferHandle = osMessageQueueNew(BUFFER_SIZE, sizeof(int), NULL);
osThreadNew(StartDefaultTask, NULL, NULL);
osThreadNew(StartDefaultTask, NULL, NULL);
osThreadNew(StartTask02, NULL, NULL);
osThreadNew(StartTask02, NULL, NULL);
}
3.总结FreeRTOS中同步和互斥的五种方法的使用方法
队列:
(1)创建队列,分为动态创建和静态创建,动态创建使用xQueueCreate函数进行创建,静态创建使用xQueueCreateStatic函数进行创建。
(2)写操作,队列写操作也分为两种:一种是在中断中使用的一个函数:xQueueSendToBackFromISR,另一种是在任务中使用的:xQueueSendToBack。
(3)读操作,读函数也分为两种:一种是在中断中进行队列的读取(xQueueReceiveFromISR),另一种是在任务中进行队列的读取。(xQueueReceive)
信号量:
(1)创建信号量,分为创建二进制信号量xSemaphoreCreateBinary,创建计数型信号量xSemaphoreCreateCounting。
(2)获取信号量(信号量值大于零才能被获取),根据创建时返回的id 获取二进制/计数型信号量信号量xSemaphoreTake。
(3)释放信号量,根据创建时返回的id 释放二进制/计数型信号量信号量xSemaphoreGive。
(4)销毁信号量vSemaphoreDelete。
互斥量:
(1)创建互斥量 xSemaphoreCreateMutex
(2)获取/锁定互斥量 (同获取信号量)xSemaphoreTake。
(3)释放/解锁互斥量 (同释放信号量)xSemaphoreGive。
(4)销毁互斥量 (同销毁信号量)xSemaphoreDelete
事件组:
(1)创建事件组 xEventGroupCreate。
(2)设置事件 xEventGroupSetBits 设置完成对应的等待程序将被唤醒。
(3)清除事件 xEventGroupClearBits 清除事件组中的一个或者多个事件标志。
(4)等待事件xEventGroupWaitBits 让任务等待一个或者多个事件的发生。
(5)销毁事件组 xEventGroupDelete
任务通知:
(1)任务通知函数osThreadFlagsSet
(2)等待任务通知函数osThreadFlagsWait
4.总结任务通知和其他任务通信机制的区别
(1)队列、信号量、互斥量、事件组在使用之前都需要先创建,才能使用。任务通知无需创建即可使用。
(2)队列、信号量、互斥量、事件组 多对多通信。任务通知是多对一通信,只需要知道要通知的任务ID即可。
(3)队列、信号量、互斥量、事件组需要被创建,所以消耗的资源也是比较多。任务通知不需要被创建消耗的资源少。