RT Thread核心原始碼分析 訊號量實現原理

2021-09-28 22:04:38 字數 2638 閱讀 4190

目錄概念

訊號量基本操作

訊號量初始化

獲取訊號量

釋放訊號量 總結

訊號量機概念是由荷蘭科學家dijkstr(就是解決了最短路徑問題的那哥們)引入,它是用來協調不同程序間的資料物件的,訊號量本質上而言是乙個計數器, 記錄了某個資源的訪問情況, 用來為多個程序共享的資料結構提供受控訪問。 在不同的作業系統平台,都有訊號量的實現, 雖然各個平台在實現上和概念上有些區別, 卻始終離不開如下幾個功能:

1. 訊號量初始化

建立訊號量物件,初始化計數器值

2. 獲取訊號量

獲取訊號量相當於獲取了對共享資源的訪問許可權

3. 釋放訊號量

釋放訊號量相當於釋放了對共享資源的訪問許可權

接下來就以rt-thread平台訊號量的實現進行說明

rt_err_t rt_sem_init(rt_sem_t    sem,

const char *name,

rt_uint32_t value,

rt_uint8_t flag)

訊號量的初始化的核心就是建立了乙個計數器value, rtthread為了方便管理系統資源(訊號量也是系統資源),定義了一套物件管理方法,所有的物件都需要繼承自rt_object,方便進行管理

對於像訊號量這種稀缺資源, 並不是隨時都能獲取到, 而在linux平台,獲取系統資源的操作通常都會設定乙個最大等待時間, 在這個時間超時後依然無法獲取資源,則返回,同樣的,rt-thread也有這樣的考慮,獲取訊號量介面中含有乙個等待時間,如下:

rt_err_t rt_sem_take(rt_sem_t sem, rt_int32_t time)

else

else

/* enable interrupt */

rt_hw_interrupt_enable(temp);//開中斷

/* do schedule */

rt_schedule();//重新排程

if (thread->error != rt_eok)}}

rt_object_hook_call(rt_object_take_hook, (&(sem->parent.parent)));

return rt_eok;

}

訊號量計數器也是多執行緒共享資源, 使用前後需要開關中斷.

細心的朋友會發現這裡有乙個問題,上述**可能會導致優先順序反轉。 我們在rt-thread核心原始碼分析-優先順序反轉**實現中有過分析, 因獲取系統資源導致掛起有可能會引發優先順序反轉,顯然, rt_sem_take可能會導致優先順序反轉。事實上,這也正是訊號量的優點所在,相比於互斥量,訊號量沒有所有者的概念, 實現簡單,小巧,靈活,效率高,常用在對互斥要求不嚴格的系統中。

rt_err_t rt_sem_release(rt_sem_t sem)

else

sem->value ++; /* increase value */

/* enable interrupt */

rt_hw_interrupt_enable(temp);

/* resume a thread, re-schedule */

if (need_schedule == rt_true)

rt_schedule();

return rt_eok;

}

釋放訊號量的本質是對計數器進行++操作,釋放訊號量可能會導致執行緒排程,即便當前沒有更高優先順序執行緒就緒, 釋放訊號量也會導致立即排程被訊號量掛起的執行緒。

這裡有乙個問題, 在rt_sem_release中,如果有被掛起到該訊號量的執行緒的話,將會執行rt_schedule進行排程(可以肯定的是,此時此刻,當前執行緒和系統就緒執行緒佇列中的執行緒相比,當前執行緒的優先順序是最高的, 也就是當前系統的就緒佇列中是沒有比當前執行緒優先順序更高的執行緒存在), 而rt_sem_release的實現中,如果需要排程,則不再執行sem->value++,那麼這可能會導致乙個問題, 如果執行rt_schedule,發現此時此刻就緒佇列中的執行緒優先順序都比當前執行緒優先順序低,則將不再執行排程, 則當前執行緒就會繼續執行,但是卻沒有執行sem->value++,這豈不是會導致問題,事實上,不會產生任何問題, 原因就在於rt_sem_take的實現,下面是對rt_sem_take和rt_sem_release的過程分析,去除了一些不必要的**:

rt_err_t rt_sem_take(rt_sem_t sem, rt_int32_t time)

else

else

}...

}rt_err_t rt_sem_release(rt_sem_t sem)

else

sem->value ++;

...if (need_schedule == rt_true)

rt_schedule();

return rt_eok;

}

訊號量本質上是乙個計數器, 計數器位於臨界資源中, 操作計數器時也需要開關中斷實現。 訊號量實現簡單,相比於互斥量,訊號量沒有所有者的概念, 實現簡單,小巧,靈活,效率高,但是可能會導致優先順序反轉,常用在對互斥要求不嚴格的系統中。另外,即便當前沒有更高優先順序執行緒需要排程, 釋放訊號量(mutex)也會觸發排程器執行執行緒排程。

分析核心原始碼,裝置樹

u boot需要將裝置樹在記憶體中的儲存位址傳給核心。該樹主要由三大部分組成 頭 header 結構塊 structure block 字串塊 strings block 裝置樹在記憶體中的儲存布局圖如下 1.1 頭 1.2 結構塊 struct block 扁平裝置樹結構塊是線性化的樹形結構,和字...

Linux核心 fork 原始碼分析

核心版本 linux 4.4.18 原始碼位置 這裡 接著 呼叫copy process 它設定了程序描述符以及子程序所需的任何其他核心資料結構。ftrace graph init task 初始化ftrace,核心追蹤函式呼叫。rt mutex init task 初始化鎖。copy creds ...

原始碼分析 Linux 核心工具Sparse

sparse誕生於2004年,是由linux之父開發的,目的就是提供乙個靜態檢查 的工具,從而減少linux核心的隱患。起始,在sparse之前已經有了乙個不錯的 靜態檢查工具 swat 只不過這個工具不是免費軟體,使用上有一些限制。所以linus自己開發了乙個靜態檢查工具。核心 中有乙個對spar...