跳至主要內容

资源管理

大约 3 分钟

资源管理

数据同步与信号量

  • 信号量不是一个具体的值, 而是一种多任务同步机制
  • 等待 (Take) 信号量的任务会阻塞, 直到有任务给出 (Give) 信号量
  • 不同于回调, 信号量机制可以保证每个任务相互独立与任务之间正常调度
  • 可通过各个任务等待上一个信号量与给出下一个信号量, 规定各个任务的调度顺序
  • 与消息队列相同, 信号量应作为全局变量使用

二进制信号量

  • 二进制信号量中信号量的数目最多为 1
  • 二进制信号量无论同时给出多少次, 只能被读取一次
  • 因此当资源给出的频率较快时, 不应当使用二进制信号量, 否则可能导致资源丢失

计数信号量

  • 计数信号量可以被多次读取与给出

资源保护与互斥量

  • 互斥量不是一个具体的值, 而是一种资源保护机制
  • 由于任务调度机制, 当任务 A 使用资源时, 调度到同样使用此资源的任务 B 将导致混乱, 需要引入互斥量
  • 在使用特定资源前, 先等待管理这个资源的互斥量, 确保这个资源不被其他任务使用
  • 在使用结束后再给出互斥量, 使这个资源能够被使用
  • 互斥量不能在中断中操作

FreeRTOS 信号量函数

FreeRTOS 中, 三种信号量的操作函数相同

创建二进制信号量

SemaphoreHandle_t xSemaphoreCreateBinary(void)

创建计数信号量

SemaphoreHandle_t xSemaphoreCreateCounting(
     UBaseType_t uxMaxCount,
    UBaseType_t uxInitialCount );
  • uxMaxCount 计数信号量包含信号量的最大值
  • uxInitialCount 计数信号量中信号量的初始值

创建互斥量

SemaphoreHandle_t xSemaphoreCreateMutex( void )

等待信号量

BaseType_t xSemaphoreTake( 
    SemaphoreHandle_t xSemaphore, 
    TickType_t xTicksToWait )
  • xSemaphore 信号量的句柄
  • xTicksToWait 如果信号量不可用的话任务处于阻塞状态的最长时间, 设置为 portMAX_DELAY 的话任务会一直处于阻塞状态直到信号量可用, 设置为 0 的话如果信号量不可用的话会直接返回
  • 返回值 pdPASS 表示成功获取了信号量, 返回值为 pdFALSE 表示获取信号量失败

给出信号量

BaseType_t xSemaphoreGive( 
    SemaphoreHandle_t xSemaphore );
  • xSemaphore 信号量的句柄
  • 返回值 pdPASS 表示成功给予信号量, 返回值为 pdFALSE 表示给予信号量失败

在中断中给出信号量

BaseType_t xSemaphoreGiveFromISR( 
    SemaphoreHandle_t xSemaphore,
    BaseType_t *pxHigherPriorityTaskWoken) 
  • pxHigherPriorityTaskWoken 可以使用值 pdFALSE / pdTrue, 但要通过指针的形式给出, pdTRUE 时, 离开中断时, 如果有高优先级的任务因此解除阻塞, 则将优先执行此任务

CMSIS RTOS 信号量操作函数

互斥量部分

创建互斥量

osMutexId_t osMutexNew (const osMutexAttr_t * attr)	
  • attr 互斥量属性, 对于一般使用 NULL 即可

等待互斥量

osStatus_t osMutexAcquire(
    osMutexId_t mutex_id, uint32_t timeout)	

给出互斥量

osStatus_t osMutexRelease(osMutexId_t mutex_id)	

获取互斥量的来源

osThreadId_t osMutexGetOwner(osMutexId_t mutex_id)	

信号量部分

默认创建的是计数信号量

关键区

  • 另一种资源管理方法, 在关键区内, 任务不能被调度, 必须完整执行关键区内的内容

进入关键区

taskENTER_CRITICAL()

离开关键区

taskEXIT_CRITICAL()