天天看點

NCS-OS系列13 :互斥鎖NCS-OS系列13 :互斥鎖前言概念可重入鎖優先級繼承實作推薦用法配置選型

NCS-OS系列13 :互斥鎖

文章目錄

  • NCS-OS系列13 :互斥鎖
  • 前言
  • 概念
  • 可重入鎖
  • 優先級繼承
  • 實作
    • 定義一個互斥鎖
    • 鎖定互斥鎖
    • 解鎖互斥鎖
  • 推薦用法
  • 配置選型

前言

ncs 相關文章,部分為原始文檔翻譯,水準有限,如果有錯誤,歡迎指出。

本文參考連結:

https://docs.zephyrproject.org/latest/reference/kernel/synchronization/mutexes.html

概念

互斥鎖是一個核心對象,它實作了一個通用的可重入互斥鎖。互斥鎖通過確定對資源的互斥通路,允許多個線程安全地共享相關的硬體或軟體資源。

可以定義任意數量的互斥對象(僅受可用RAM的限制),每個互斥量都由它的記憶體位址來引用。

互斥量有如下關鍵屬性:

  • 鎖計數(

    lock count

    ),表示鎖住互斥鎖的線程鎖住互斥鎖的次數。計數為0表示互斥鎖已解鎖。
  • 當互斥鎖被鎖定時,擁有該互斥鎖的線程(

    owning thread

互斥量在使用前必須進行初始化,初始化後

lock count

被初始化為0。

需要使用共享資源的線程必須首先通過鎖定相關的互斥鎖獲得通路該資源的獨占權限,如果互斥鎖已經被另一個線程鎖定,請求線程可以選擇等待互斥鎖被解鎖。

在鎖定了互斥鎖之後,線程可以根據需要安全地使用相關的資源;但是,持有鎖的時間越短越好,以避免對其他想要使用資源的線程産生負面影響。當線程不再需要資源時,它必須解鎖互斥鎖以允許其他線程使用資源。

任意數量的線程都可以同時等待一個鎖定的互斥鎖。當互斥鎖被解鎖時,它就會被等待時間最長的最高優先級的線程鎖定。

可重入鎖

允許線程鎖定已經鎖定的互斥對象。這允許線程在其執行時通路相關的資源,而互斥鎖可能已經鎖定,也可能還沒有鎖定。

被一個線程反複鎖定的互斥鎖在完全解鎖之前,必須解鎖相同次數的互斥鎖,以便另一個線程可以擷取它。

優先級繼承

鎖定了互斥鎖的線程可以進行優先級繼承。這意味着如果更高優先級的線程開始等待互斥鎖,核心将臨時提高擁有互斥鎖的線程的優先級,這允許擁有互斥鎖的線程以與等待線程相同的優先級執行,進而更快地完成工作并釋放互斥鎖。一旦互斥鎖被解除鎖定,解除鎖定的線程就會将其優先級重置為鎖定互斥鎖之前的級别。

注意,由于優先級繼承,

CONFIG_PRIORITY_CEILING

配置選項限制了核心可以将線程的優先級提高到多高。預設值0允許無限提升。

實作

定義一個互斥鎖

互斥是使用

k_mutex

類型的變量定義的。然後必須通過調用

k_mutex_init()

來初始化它。

下面代碼定義了一個互斥鎖:

struct k_mutex my_mutex;

k_mutex_init(&my_mutex);
           

通用也可以通過調用

K_MUTEX_DEFINE

來在編一階段靜态定義一個互斥鎖。

下面代碼和上面代碼實作相同的功能:

鎖定互斥鎖

互斥鎖通過

k_mutex_lock()

進行鎖定。

下面代碼進行互斥鎖的鎖定,如果互斥鎖已經被鎖定,那麼無限期的等待互斥鎖的解鎖:

struct k_mutex my_mutex;
k_mutex_init(&my_mutex);

k_mutex_lock(&my_mutex, K_FOREVER);
           

下面代碼等待互斥鎖解鎖100ms,否則上報一個錯誤報告:

struct k_mutex my_mutex;
k_mutex_init(&my_mutex);
if (k_mutex_lock(&my_mutex, K_MSEC(100)) == 0) {
    /* mutex successfully locked */
} else {
    printf("Cannot lock XYZ display\n");
}
           

解鎖互斥鎖

互斥鎖通過調用

k_mutex_unlock()

進行解鎖。

下面代碼示範如何進行互斥鎖的解鎖:

推薦用法

使用互斥鎖來提供對資源(例如實體裝置)的獨占通路。

配置選型

  • CONFIG_PRIORITY_CEILING