硬汉嵌入式论坛

 找回密码
 立即注册
查看: 1350|回复: 2
收起左侧

[FreeRTOS] FreeRTOS 互斥锁和二值信号量

[复制链接]

102

主题

573

回帖

894

积分

金牌会员

积分
894
QQ
发表于 2024-11-18 16:39:09 | 显示全部楼层 |阅读模式
本帖最后由 会飞的猪_2020 于 2024-11-18 16:41 编辑

互斥锁用于互斥。

信号量用于任务间同步。

刚才试了一下,xSemaphoreCreateMutex创建互斥量之后,内置的计数值应该是1。
也就是说下面这个伪代码,tcp_client_test还是会执行。
[C] 纯文本查看 复制代码
void main(void) {
    ....
    ip_mutex = xSemaphoreCreateMutex();
    ....
}
static void _init(void *p)
{
    log_i("task wifi init");
    while (1) {
        if (xSemaphoreTake(ip_mutex, portMAX_DELAY) == pdTRUE) {                    
            extern int tcp_client_test(void);
            tcp_client_test();
        }
    }
}


而改成xSemaphoreCreateBinary之后,它内部的计数值应该是0了。就不会直接执行了。



感觉互斥量不应该用于任务之间同步,应该用于保护共享的资源。
例如下面这个保护同一个串口发送。
[C] 纯文本查看 复制代码
/**
 * @brief 串口发送
 * @param {COM_PORT_E} _ucPort
 * @param {uint8_t} *_ucaBuf
 * @param {uint16_t} _usLen
 * @return {*}
 */
int32_t comSendBuf(COM_PORT_E _ucPort, uint8_t *_ucaBuf, uint16_t _usLen)
{
    UART_T *pUart;
    int ret = 0;
    pUart = ComToUart(_ucPort);

    if (pUart == 0) {
        return -1;
    }
    xSemaphoreTake(pUart->mutex, portMAX_DELAY);
    if (pUart->SendBefor != NULL) {
        pUart->SendBefor(pUart->com);
    }
    ret = hosal_uart_send(pUart->uart, _ucaBuf, _usLen);
    hosal_uart_ioctl(pUart->uart, HOSAL_UART_FLUSH, NULL); //阻塞发送
    if (pUart->SendOver != NULL) {
        pUart->SendOver(pUart->com);
    }
    xSemaphoreGive(pUart->mutex);
    return ret;
}



回复

使用道具 举报

102

主题

573

回帖

894

积分

金牌会员

积分
894
QQ
 楼主| 发表于 2024-11-18 16:45:00 | 显示全部楼层
本帖最后由 会飞的猪_2020 于 2024-11-18 16:48 编辑

GPT对于互斥量信号翻转的解释(和我楼主位的测试无关,仅作为好奇问了一下AI)

GitHub Copilot
当我们讨论 优先级反转 时,主要是指 低优先级任务持有资源并阻塞高优先级任务,导致本应该先执行的高优先级任务被拖延。
让我们用一个更实际的例子来解释这一现象。
示例:共享资源中的二值信号量和优先级反转
假设我们有三个任务:
  • Task A:高优先级任务
  • Task B:中等优先级任务
  • Task C:低优先级任务

这三个任务都需要访问一个共享资源(比如一个文件)。为了避免多个任务同时访问这个资源,系统使用一个二值信号量来保护这个资源。
执行流程:
  • Task C(低优先级) 首先获取了信号量并开始访问共享资源(文件)。此时,任务 C 正在处理文件操作,可能需要一段时间(比如 5 秒)。
  • Task A(高优先级) 在任务 C 访问资源期间,试图获取信号量访问相同的共享资源。然而,信号量被任务 C 持有,因此任务 A 被阻塞,必须等待任务 C 释放资源。
  • 就在任务 A 被阻塞的同时,Task B(中等优先级) 执行并且也尝试获取信号量。由于任务 A 被阻塞在信号量上,任务 B 会获取信号量并开始执行。
  • 优先级反转:此时,任务 A(高优先级)被任务 C(低优先级)阻塞,而任务 B(中等优先级)又能顺利执行。这种情况下,任务 A 的执行被拖延了很长时间,而任务 B 的优先级本不应该阻碍任务 A 的执行。


结果:
  • 任务 A(高优先级) 实际上被 任务 B(中等优先级) 阻塞,因为任务 B 获取到了信号量并且执行了。任务 C(低优先级) 占用了资源并导致任务 A 的执行延迟,这就叫做优先级反转。
  • 在理想情况下,任务 A 应该在任务 C 完成之后立刻执行,但由于中等优先级任务 B 干扰了它,任务 A 被延迟了。

解决方法:
为了避免这种情况,我们通常会使用 优先级继承协议(Priority Inheritance Protocol),确保 任务 C 在持有信号量时能够“继承”任务 A 的高优先级,从而减少优先级反转的影响。
这种机制确保了低优先级任务在持有资源时不会长时间阻塞高优先级任务。



回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117530
QQ
发表于 2024-11-19 10:12:16 | 显示全部楼层
互斥信号量正确姿势就是要在同一个任务里面成对使用。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2025-8-12 22:32 , Processed in 0.038363 second(s), 24 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表