使用STM32編寫一個簡單的RTOS:2.對象管理

參考資料:RTT官網文檔
關鍵字:分析RT-Thread源碼、stm32、RTOS、對象管理器。

內核對象管理架構

RT-Thread 採用內核對象管理系統來訪問 / 管理所有內核對象,內核對象包含了內核中絕大部分設施,這些內核對象可以是靜態分配的靜態對象,也可以是從系統內存堆中分配的動態對象。

通過這種內核對象的設計方式,RT-Thread 做到了不依賴於具體的內存分配方式,系統的靈活性得到極大的提高。

RT-Thread 內核對象包括:線程,信號量,互斥量,事件,郵箱,消息隊列和定時器,內存池,設備驅動等。對象容器中包含了每類內核對象的信息,包括對象類型,大小等。對象容器給每類內核對象分配了一個鏈表,所有的內核對象都被鏈接到該鏈表上,如圖 RT-Thread 的內核對象容器及鏈表如下圖所示:
在這裏插入圖片描述
下圖則顯示了 RT-Thread 中各類內核對象的派生和繼承關係。對於每一種具體內核對象和對象控制塊,除了基本結構外,還有自己的擴展屬性(私有屬性),例如,對於線程控制塊,在基類對象基礎上進行擴展,增加了線程狀態、優先級等屬性。這些屬性在基類對象的操作中不會用到,只有在與具體線程相關的操作中才會使用。因此從面向對象的觀點,可以認爲每一種具體對象是抽象對象的派生,繼承了基本對象的屬性並在此基礎上擴展了與自己相關的屬性。
在這裏插入圖片描述

在對象管理模塊中,定義了通用的數據結構,用來保存各種對象的共同屬性,各種具體對象只需要在此基礎上加上自己的某些特別的屬性,就可以清楚的表示自己的特徵。

這種設計方法的優點有:

1、提高了系統的可重用性和擴展性,增加新的對象類別很容易,只需要繼承通用對象的屬性再加少量擴展即可。
2、提供統一的對象操作方式,簡化了各種具體對象的操作,提高了系統的可靠性。

上圖中由對象控制塊 rt_object 派生出來的有:線程對象、內存池對象、定時器對象、設備對象和 IPC 對象(IPC:Inter-Process Communication,進程間通信。在 RT-Thread 實時操作系統中,IPC 對象的作用是進行線程間同步與通信);由 IPC 對象派生出信號量、互斥量、事件、郵箱與消息隊列、信號等對象。

代碼分析

內核對象容器的數據結構:

struct rt_object_information
{
/* 對象類型 /
enum rt_object_class_type type;
/
對象鏈表 /
rt_list_t object_list;
/
對象大小 */
rt_size_t object_size;
};
一類對象由一個 rt_object_information 結構體來管理,每一個這類對象的具體實例都通過鏈表的形式掛接在 object_list 上。而這一類對象的內存塊尺寸由 object_size 標識出來(每一類對象的具體實例,他們佔有的內存塊大小都是相同的)。

官網文檔已經寫的比較詳細了,這裏就直接複製了。下面就以線程類型直接分析代碼了。

#define _OBJ_CONTAINER_LIST_INIT(c)     \
    {&(rt_object_container[c].object_list), &(rt_object_container[c].object_list)}
struct rt_object_information rt_object_container[RT_Object_Class_Unknown] =
{
    /* initialize object container - thread */
    {RT_Object_Class_Thread, _OBJ_CONTAINER_LIST_INIT(RT_Object_Class_Thread), sizeof(struct rt_thread)},
...
}

在全局的對象容器中定義時就對其初始化了,_OBJ_CONTAINER_LIST_INIT這個宏裏面的操作是將object_list的prev和next指向了自身。這裏我們以 rt_object_init爲例,和rt_object_allocate功能一樣,只不過一個是靜態一個是動態分配內存的。

rt_err_t rt_thread_init(struct rt_thread *thread, ...)
{
	...
	
	/* init thread object */
	rt_object_init((rt_object_t)thread, RT_Object_Class_Thread, name);
	...
}

void rt_object_init(struct rt_object         *object,
                    enum rt_object_class_type type,
                    const char               *name)
{
    ...
    information = &rt_object_container[type];
    ...

    /* insert object into information object list */
    rt_list_insert_after(&(information->object_list), &(object->list));
    ...
}

rt_object_init的作用就是在容器中找到其類型的頭節點,通過rt_list_insert_after將線程插入對象容器中。
在這裏插入圖片描述

對象容器的代碼比較少也比較簡單,用對象容器主要是方便管理和查找同一類型的對象。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章