我正在尝试锁定 ESP32。显然,实现锁有不同的方式:

  • 有默认的C++互斥库:
    #include <mutex>
    
    std::mutex mtx;
    
    mtx.lock();
    
    mtx.unlock();
    
  • 还有 implementation from RTOS :
    SemaphoreHandle_t xMutex = xSemaphoreCreateMutex();
    
    xSemaphoreTake(xMutex, portMAX_DELAY);
    
    xSemaphoreGive(xMutex);
    

  • 是否存在我应该注意的根本差异?
    或者它们是等价的?

    最佳答案

    假设您使用的是 ESP-IDF SDK,该工具链基于 GCC 5.2,针对 xtensa-lx106 指令集,带有部分开源的 C 运行时库。

    GNU libstdc++ 中的 std::mutex 委托(delegate)给 pthread_mutex_lock/unlock 调用。 ESP-IDF SDK 包含一个 pthread emulation layer ,我们可以在其中看到 pthread_mutex_lock pthread_mutex_unlock 的实际作用:

    static int IRAM_ATTR pthread_mutex_lock_internal(esp_pthread_mutex_t *mux, TickType_t tmo)
    {
        if (!mux) {
            return EINVAL;
        }
    
        if ((mux->type == PTHREAD_MUTEX_ERRORCHECK) &&
            (xSemaphoreGetMutexHolder(mux->sem) == xTaskGetCurrentTaskHandle())) {
            return EDEADLK;
        }
    
        if (mux->type == PTHREAD_MUTEX_RECURSIVE) {
            if (xSemaphoreTakeRecursive(mux->sem, tmo) != pdTRUE) {
                return EBUSY;
            }
        } else {
            if (xSemaphoreTake(mux->sem, tmo) != pdTRUE) {
                return EBUSY;
            }
        }
    
        return 0;
    }
    
    int IRAM_ATTR pthread_mutex_unlock(pthread_mutex_t *mutex)
    {
        esp_pthread_mutex_t *mux;
    
        if (!mutex) {
            return EINVAL;
        }
        mux = (esp_pthread_mutex_t *)*mutex;
        if (!mux) {
            return EINVAL;
        }
    
        if (((mux->type == PTHREAD_MUTEX_RECURSIVE) ||
            (mux->type == PTHREAD_MUTEX_ERRORCHECK)) &&
            (xSemaphoreGetMutexHolder(mux->sem) != xTaskGetCurrentTaskHandle())) {
            return EPERM;
        }
    
        int ret;
        if (mux->type == PTHREAD_MUTEX_RECURSIVE) {
            ret = xSemaphoreGiveRecursive(mux->sem);
        } else {
            ret = xSemaphoreGive(mux->sem);
        }
        if (ret != pdTRUE) {
            assert(false && "Failed to unlock mutex!");
        }
        return 0;
    }
    

    如您所见,它主要将调用委托(delegate)给 RTOS 信号量 API,并进行一些额外的检查。

    您可能不需要/想要这些检查。考虑到 esp32 芯片的微小 i-cache 和极其缓慢的串行 RAM,我更愿意尽可能靠近硬件(即不要使用 std::mutex,除非它完全满足您的需要)。

    关于c++ - C++ mutex 和 RTOS xMutex 的区别,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57430102/

    10-15 09:59