我想知道我是否可以在任务中获取互斥锁,但通过调用外部函数。 这是我下面的代码:
void TakeMutexDelay50(SemaphoreHandle_t mutex)
{
while(xSemaphoreTake(mutex, 10) == pdFALSE)
{
vTaskDelay(50);
}
}
bool ContinueTaskCopy()
{
TakeMutexDelay50(ContinueTask_mutex);
bool Copy = ContinueTask;
xSemaphoreGive(ContinueTask_mutex);
return Copy;
}
基本上,我的任务调用函数 ContinueTaskCopy((。这是好习惯吗?
上面的代码将起作用,但是如果您在while循环中没有执行任何操作来获取互斥锁,则可以将超时设置为portMAX_DELAY,并避免每50个时钟周期进行一次所有上下文切换。
回答您的疑问 - 是的,这段代码将起作用。从技术角度来看,RTOS代码本身并不真正关心获取或释放互斥锁的函数,重要的是执行代码的任务(或者更具体地说是上下文,因为我们还包括中断(。
事实上,不久前(我认为是一些 FreeRTOS 7 版本?(他们在释放互斥锁的函数中引入了一个额外的检查,该检查将释放互斥锁的任务与保存互斥锁的任务进行比较。如果它不是同一个,它实际上会失败一个断言,这实际上是一个无限循环,阻止你的任务继续,以便你可以注意到并解决问题(关于断言有大量的评论可以帮助你诊断问题(。这样做是因为互斥锁用于保护资源 - 想想SD卡访问,显示访问等 - 并且从一个任务中获取互斥锁并从另一个任务释放它违背了整个想法,或者至少指向臭代码。如果您需要执行此类操作,则可能希望改用信号量。
现在至于你问题的第二部分 - 这是否是一个很好的做法 - 我会说这取决于你让它变得多么复杂,但总的来说我认为这是有问题的。通常,在互斥锁上运行的代码如下所示:
if(xSemaphoreTake(mutex, waitTime) == pdTRUE)
{
doResourceOperation();
xSemaphoreGive(mutex);
}
这很简单,很容易理解,因为这就是大多数人习惯于编写这样的代码的方式。它几乎避免了这个互斥锁的整类问题,如果你开始使代码复杂化并释放它("为什么不发布?","谁持有这个互斥锁?","我陷入僵局吗?"(。这类问题往往难以调试,有时甚至难以修复,因为它可能涉及重新排列代码的某些部分。
给出一般建议 - 保持简单。看到围绕互斥锁做一些奇怪的事情通常意味着那里有一些可疑的事情。可能出现一些令人讨厌的死锁或竞争条件。与您的示例一样,与其尝试每 50 毫秒永远获取一次互斥锁直到成功,不如通过指定xSemaphoreTake
的延迟时间portMAX_DELAY
并将其放入使用资源并释放互斥锁的同一函数中来永远等待。