RTOS学习记录2:同步与互斥

发布时间 2023-09-15 21:22:38作者: zxkic

同步和互斥

循环检测某个变量是否已经释放的方式占用较多,效率较低。需要加一些函数,让其进入到blocked(阻塞)状态

Task3和Task4同时使用串口打印信息时,没有设定mutex,因此打印出来的内容各有混杂。通过设定USARTFlag来实现互斥+Delay让出优先权。

正确性和效率:

1.队列FIFO:传送带,流水线。

  实现同步:

  1.创建队列:动态和静态两种方式。xQueueHandle() 

  2.Task1进行xQueueSend,Task2进行xQueueReceive

  实现互斥:

  1. GetUARTLock通过QueueReceive实现,PutUARTLock通过QueueSend实现。但是会出现问题,一直只有task4运行——》通过Delay来让出抢占权

  分辨数据源

typedef struct {
    ID_t eDataID;
    int32_t lDataValue;
}Data_t;

  邮箱

  队列集:

  1.创建队列

  2.创建队列集

  3.把队列添加到队列集

  4.创建任务:队列1和2都是普通的读或写,队列3监测队列1和2。

2.事件组

typedef struct EventGroupDef_t
{
    EventBits_t uxEventBits;   //每个bit表示一个事件
    List_t xTasksWaitingForBits; /*< List of tasks waiting for a bit to be set. */

    #if ( configUSE_TRACE_FACILITY == 1 )
        UBaseType_t uxEventGroupNumber;
    #endif

    #if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
        uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the event group is statically allocated to ensure no attempt is made to free the memory. */
    #endif
} EventGroup_t;

 正常用法:create -> setbits -> waitbits;但是事件组只能传递状态,需要传递的数据需要用队列或其他结构来传递。

同步点:xEventGroupSync()函数

3.信号量(semaphore)——计数值

 SemaphoreHandle_t实际上也是QueueHandle_t类型。其中的uxMessagesWaiting表示其value

 give和take

Task1和Task2之间使用了flag,但是效率比较差

 使用信号量能保证同步,但是不能保证传输数据的安全性

 实现互斥:先give,每次使用时take,然后释放give

4.任务通知:多对一

使用任务通知时,任务结构体TCB(Task Control Block)就包含了内部对象,可以直接接收别人发送出来的通知。

使用ucNotifyState切换任务状态,使用ulNotifiedValue来传递消息。

轻量级信号量:take和give通过ulTaskNotifyTake、ulTaskNotifyGive实现,不需要创建信号量 

轻量级队列:

轻量级事件组: 

5.互斥量mutex,也需要解决优先级问题

对临界资源的保护,谁lock,谁unlock(有进程会give,然后自己再take)。解决互斥量和优先级反转的需求。

1)优先级反转:优先级C>B>A,但是C需要A释放资源,A不释放,则会一直让B执行。B持续执行,则A得不到运行的机会,导致C也不能运行。

2)二次上锁:任务1lock了锁1,结果任务1里面的调用了任务2,任务2也请求锁1,导致死锁。——通过递归锁解决

  常规使用:与二进制信号量的唯一差别是初始化函数,其余用法一模一样:

/*初始化函数*/
//xSemUART = xSemaphoreCreateBinary();
//xSemaphoreGive(xSemUART);
xSemUART = xSemaphoreCreateMutex();

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

  优先级反转

  

  互斥量的缺陷和递归锁:

    会出现监守自盗(别人使用了,强盗想用,自己释放,然后再抢占),不能实现谁持有谁释放。 

    该问题可以通过递归锁来解决