FreeRTOS如何查询当前持有二进制信号量的任务
结论
FreeRTOS 原生没有直接提供查询二进制信号量持有任务的公共API,这和二进制信号量的设计定位直接相关:二进制信号量本身没有要求「take和give操作必须在同一个任务中执行」,因此内核默认不会记录它的持有者信息。
可行方案
方案1:改用互斥量(符合原生设计的最优方案)
如果你的场景不需要在中断中操作该同步对象,完全可以把myBinarySemaphore替换为互斥量(通过xSemaphoreCreateMutex()创建)。互斥量为了实现优先级继承机制,内部默认会记录持有者任务的TCB指针,你可以通过访问内核内部结构体拿到持有者信息。
注意:该方法用到的结构体成员属于内核内部实现,不同版本FreeRTOS的结构体定义可能有差异,需要和你使用的内核版本匹配。
代码示例:
// 必须引入内核内部头文件,才能访问信号量、任务的内部结构体 #include "task.h" #include "semphr.h" // 自定义获取互斥量持有者的函数 TaskHandle_t xGetMutexOwner(SemaphoreHandle_t xMutex) { if(xMutex == NULL) return NULL; // 互斥量内部的pxMutexHolder成员就是持有者任务的TCB指针 return ((Semaphore_t *)xMutex)->pxMutexHolder; } void taskC(void *pvParameters) { // 注意:创建taskA、taskB时需要提前保存它们的任务句柄,不能直接用函数名比较 extern TaskHandle_t xTaskAHandle, xTaskBHandle; for(;;) { TaskHandle_t xOwner = xGetMutexOwner(myMutex); if(xOwner == xTaskAHandle) printf("taskA has the mutex\n"); else if (xOwner == xTaskBHandle) printf("taskB has the mutex\n"); else printf("No task holds the mutex\n"); // 必须加延时,否则taskC会占满CPU,其他任务无法拿到执行权 vTaskDelay(pdMS_TO_TICKS(10)); } }
方案2:必须用二进制信号量的场景,自行封装接口
如果你确实需要使用二进制信号量(比如需要在中断中执行give操作),只需要对信号量的take、give接口做一层简单封装,用全局变量记录持有者即可,实现成本很低:
// 全局变量记录信号量持有者 TaskHandle_t xBinarySemHolder = NULL; // 封装take接口 BaseType_t xMyBinarySemTake(SemaphoreHandle_t xSem, TickType_t xTicksToWait) { BaseType_t xRet = xSemaphoreTake(xSem, xTicksToWait); if(xRet == pdTRUE) { xBinarySemHolder = xTaskGetCurrentTaskHandle(); } return xRet; } // 封装任务上下文的give接口 BaseType_t xMyBinarySemGive(SemaphoreHandle_t xSem) { BaseType_t xRet = xSemaphoreGive(xSem); if(xRet == pdTRUE) { xBinarySemHolder = NULL; } return xRet; } // 封装中断上下文的give接口(如果需要) BaseType_t xMyBinarySemGiveFromISR(SemaphoreHandle_t xSem, BaseType_t *pxHigherPriorityTaskWoken) { BaseType_t xRet = xSemaphoreGiveFromISR(xSem, pxHigherPriorityTaskWoken); if(xRet == pdTRUE) { xBinarySemHolder = NULL; } return xRet; }
之后把taskA、taskB中原来的xSemaphoreTake、xSemaphoreGive替换为上面的封装接口,taskC直接读取xBinarySemHolder和任务句柄比较即可。
注意事项
查询信号量持有者的逻辑本身存在天然竞态:你查询到的结果仅代表查询瞬间的状态,下一刻持有者可能就已经释放了信号量,不要在生产代码的核心逻辑中强依赖该查询结果。
内容的提问来源于stack exchange,提问作者PLB
相关产品推荐
相关产品推荐

