mutex - 互斥锁如何保证 freeRTOS 中的所有权?
问题描述
我正在使用 esp32 在 freeRTOS 中使用 Mutex。在一些文档中,我已经阅读了互斥锁保证所有权,这意味着如果一个线程(我们将其命名为 task_A)锁定了一个关键资源(获取令牌),其他线程(task_B 和 task_C)将保持在等待模式下等待该资源被解锁由锁定它的同一线程(即task_A)。我试图通过设置其他任务(task_B 和 task_C)来证明这一点,以便在开始做任何事情之前给出一个令牌,然后它会尝试从互斥锁持有者那里获取一个令牌,这令人惊讶地工作而没有显示任何错误的孩子. 好吧,我用来验证或显示事情如何工作的方法我创建了一个显示函数,该函数读取每个任务发布(设置和清除)的事件(当它处于等待模式时,它会设置等待位,如果它' s 工作它会设置工作位等等......,你明白了)。以及一个简单的 printf() 以防获取或提供函数(xSemaphoreTake != true 和 xSemaphoreGive != true)出错。
我不能使用调试模式,因为我没有任何类型的微控制器调试器。
这是我正在尝试做的一个示例:我创建了许多任务,每个任务都会调用此函数,但在不同的时间使用不同的设置。
void vVirtualResource(int taskId, int runTime_ms){
int delay_tick = 10;
int currentTime_tick = 0;
int stopTime_tick = runTime_ms/portTICK_PERIOD_MS;
if(xSemaphoreGive(xMutex)!=true){
printf("Something wrong in giving first mutex's token in task id: %d\n", taskId);
}
while(xSemaphoreTake(xMutex, 10000/portTICK_PERIOD_MS) != true){
vTaskDelay(1000/portTICK_PERIOD_MS);
}
// notify that the task with <<task id>> is currently running and using this resource
switch (taskId)
{
case 1:
xEventGroupClearBits(xMutexEvent, EVENTMASK_MUTEXTSK1);
xEventGroupSetBits(xMutexEvent, EVENTRUN_MUTEXTSK1);
break;
case 2:
xEventGroupClearBits(xMutexEvent, EVENTMASK_MUTEXTSK2);
xEventGroupSetBits(xMutexEvent, EVENTRUN_MUTEXTSK2);
break;
case 3:
xEventGroupClearBits(xMutexEvent, EVENTMASK_MUTEXTSK3);
xEventGroupSetBits(xMutexEvent, EVENTRUN_MUTEXTSK3);
break;
default:
break;
}
// start running the resource
while(currentTime_tick<stopTime_tick){
vTaskDelay(delay_tick);
currentTime_tick += delay_tick;
}
// gives back the token
if(xSemaphoreGive(xMutex)!=true){
printf("Something wrong in giving mutex's token in task id: %d\n", taskId);
}
}
您会注意到第一次,将开始在处理器中运行的第一个任务将打印出第一条错误消息,因为当互斥锁持有者中仍有令牌时它无法提供令牌,这是正常的,所以我忽略它。
希望有人可以向我解释互斥锁如何使用 freeRTOS 中的代码保证所有权。首先,我没有使用第一个 xSemaphoreGive 函数,它运行良好。但这并不意味着它可以保证任何事情。或者我编码不正确。
谢谢你。
解决方案
您的示例非常复杂,我也没有看到明确的代码task_A
,task_B
或者task_C
我将尝试解释一个更简单的示例,希望能解释互斥锁如何保证资源所有权。
使用互斥锁的一般方法如下:
void doWork()
{
// attempt to take mutex
if(xSemaphoreTake(mutex, WAIT_TIME) == pdTRUE)
{
// mutex taken - do work
...
// release mutex
xSemaphoreGive(mutex);
}
else
{
// failed to take mutex for 'WAIT_TIME' amount of time
}
}
上面的doWork
函数是可能被多个线程同时调用,需要保护的函数。对于需要保护的给定资源上的每个功能,此模式重复。如果资源更复杂,一个好方法是保护线程可调用的最顶层函数,然后如果成功采用互斥锁,则调用执行实际工作的内部函数。
您所说的所有权保证是声明下可能不会有多个上下文(线程,还有中断)if(xSemaphoreTake(mutex, WAIT_TIME) == pdTRUE)
。换句话说,如果一个上下文成功地获取了互斥锁,则保证没有其他上下文也能够获取它,除非原始上下文xSemaphoreGive
首先释放它。
现在至于您的场景-虽然我并不完全清楚它应该如何工作,但我可以看到您的代码有两个问题:
xSemaphoreGive
在函数的开头 - 不要那样做。互斥锁默认是“给予”的,如果你不是第一个“接受”它的人,你就不应该“给予”它。总是把一个xSemaphoreGive
下一个成功xSemaphoreTake
而无处可去。此代码块:
while(xSemaphoreTake(xMutex, 10000/portTICK_PERIOD_MS) != true){ vTaskDelay(1000/portTICK_PERIOD_MS); }
如果您需要等待互斥锁更长的时间 - 指定更长的时间。如果您想要无限等待,只需指定最长可能时间 (
0xFFFFFFFF
)。在您的场景中,您每 10 秒轮询一次互斥锁,然后延迟 1 秒,在此期间互斥锁未实际检查,这意味着在其他线程释放互斥锁后,您将不得不等待近一秒钟开始在请求它的当前线程中工作。等待互斥锁已经由 RTOS 以最佳方式完成 - 一旦它被释放,它会唤醒当前等待互斥锁的最高优先级任务,没有必要做更多的事情。
如果我要就如何修复您的示例提供建议 - 简化它并且不要做超出需要的操作,例如额外调用xSemaphoreGive
或实现您自己的等待互斥锁。将执行某些工作的代码部分隔离到一个单独的函数中,该函数xSemaphoreTake
在最顶部执行一次调用,并且xSemaphoreGive
仅在xSemaphoreTake
成功时才进行一次调用。然后从不同的线程调用这个函数来测试它是否有效。
推荐阅读
- flutter - _$CustomClass 显示“返回类型“Type”不是“CustomClass”的错误,由匿名闭包定义。`
- javascript -
我应该使用
<a href="url">Something/>
因此,当我单击它时,它会将我重定向到我的 URL。
但现在我想对 onClick 方法做同样的事情(使用我的路由器)。
在我的代码中,我尝试使用它:
- java - 如何在 RSA 中进行密钥交换以进行解密
- java - 我如何让我的世界玩家看一个块
- c - 如何将位填充到 C 中的字符串?
- c - 有人可以知道如何处理吗?
- spring-boot - 为什么 RemoteTokenServices 会频繁调用 UAA?
- c++ - 我如何在 c plus plus 中更改分配的类值
- python - 如何在 django html 中切片文本?
- xamarin - 如何记住选择器的选择,我使用 montemagno 的 xamarin.plugins.settings 并且我不知道如何获得正确的语法