www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當(dāng)前位置:首頁 > 公眾號精選 > 嵌入式IoT

RT-Thread的對象容器設(shè)計思想淺析


  • 1.本文概述

  • 2.對象容器

  • 3.對象容器的管理

  • 4.手動去解析對象容器

  • 5.總結(jié)


1.本文概述

最近在學(xué)習(xí)RT-Thread操作系統(tǒng)的內(nèi)核部分設(shè)計。RT-Thread的面向?qū)ο缶幊趟枷敕浅5那擅?,可以看我之前的寫的文章?

RT-Thread面向?qū)ο缶幊趟悸窚\析

而對象(rt_object)的管理又是一個可以深入理解的地方。簡單的說,就是我們創(chuàng)建線程,或者創(chuàng)建郵箱,創(chuàng)建信號量等,最后都抽象成對象的管理。

看一下上面的圖例。用文字表述就是,所有的線程、IPC、設(shè)備創(chuàng)建的時候,都會通過鏈表被掛載在對象容器中。

2.對象容器

結(jié)合上一章的圖不難理解,對象容器就是一個二維的數(shù)組,對象的類型以及具體某個對象的鏈表。

在rt-thread中,對象容器的代碼實現(xiàn)是一個靜態(tài)的二維數(shù)組。

可以查看rt-thread\src\object.c的具體數(shù)組實現(xiàn):

#define _OBJ_CONTAINER_LIST_INIT(c)     \
 {&(rt_object_container[c].object_list), &(rt_object_container[c].object_list)} static struct rt_object_information rt_object_container[RT_Object_Info_Unknown] =
{ /* initialize object container - thread */ {RT_Object_Class_Thread, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Thread), sizeof(struct rt_thread)}, #ifdef RT_USING_SEMAPHORE /* initialize object container - semaphore */ {RT_Object_Class_Semaphore, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Semaphore), sizeof(struct rt_semaphore)}, #endif #ifdef RT_USING_MUTEX /* initialize object container - mutex */ {RT_Object_Class_Mutex, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Mutex), sizeof(struct rt_mutex)}, #endif #ifdef RT_USING_EVENT /* initialize object container - event */ {RT_Object_Class_Event, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Event), sizeof(struct rt_event)}, #endif #ifdef RT_USING_MAILBOX /* initialize object container - mailbox */ {RT_Object_Class_MailBox, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MailBox), sizeof(struct rt_mailbox)}, #endif #ifdef RT_USING_MESSAGEQUEUE /* initialize object container - message queue */ {RT_Object_Class_MessageQueue, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MessageQueue), sizeof(struct rt_messagequeue)}, #endif #ifdef RT_USING_MEMHEAP /* initialize object container - memory heap */ {RT_Object_Class_MemHeap, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MemHeap), sizeof(struct rt_memheap)}, #endif #ifdef RT_USING_MEMPOOL /* initialize object container - memory pool */ {RT_Object_Class_MemPool, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MemPool), sizeof(struct rt_mempool)}, #endif #ifdef RT_USING_DEVICE /* initialize object container - device */ {RT_Object_Class_Device, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Device), sizeof(struct rt_device)}, #endif /* initialize object container - timer */ {RT_Object_Class_Timer, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Timer), sizeof(struct rt_timer)}, #ifdef RT_USING_MODULE /* initialize object container - module */ {RT_Object_Class_Module, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Module), sizeof(struct rt_dlmodule)}, #endif };

其中rt_object_information的定義

struct rt_object_information { enum rt_object_class_type type; /**< object class type */ rt_list_t object_list; /**< object list */ rt_size_t object_size; /**< object size */ };

也就是對象容器的屬性有大小,也有對象數(shù)據(jù)鏈表。當(dāng)任意時刻,獲取到rt_object_container[RT_Object_Info_Unknown]的地址,然后解析,即可得到當(dāng)前系統(tǒng)中線程的信息、IPC的信息以及設(shè)備狀態(tài)信息,這樣去實現(xiàn)類似于PS命令就十分簡單了。

事實上,rt-thread中的list_thread、list_sem等函數(shù)的具體實現(xiàn)也是基于這個對象容器獲取到的。

3.對象容器的管理

基于RT-Thread的對象的思想,對象管理肯定有創(chuàng)建、脫離這樣的操作。

具體看一下線程創(chuàng)建的實例。

當(dāng)調(diào)用rt_thread_create函數(shù)去創(chuàng)建線程時,會調(diào)用下面函數(shù)去創(chuàng)建一個對象。

thread = (struct rt_thread *)rt_object_allocate(RT_Object_Class_Thread,
 name);

而這個申請對象函數(shù)的實現(xiàn)其實就是從對象容器中插入一個線程

information = rt_object_get_information(type);//得到對象容器的thread對象 

接著初始化對應(yīng)的線程對象,后插入線程對象到容器中。

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

然后對象容器中就存在這個線程的鏈表了,通過查詢鏈表獲得具體的線程信息。

當(dāng)線程delete的時候,也是調(diào)用這個函數(shù),從而將鏈表從對象中脫離。

rt_list_insert_after(&rt_thread_defunct, &(thread->tlist));

在rt-thread中,很多操作就是通過這種方式實現(xiàn)線程的創(chuàng)建和銷毀的。

4.手動去解析對象容器

這確實是非常有意思的事情,通過一個地址,就可以獲取系統(tǒng)的整個運(yùn)行狀態(tài)信息。

extern struct rt_object_information rt_object_container[]; rt_uint8_t * my_addr = (rt_uint8_t *)rt_object_container; struct rt_object_information * t32_rt_thread_container = (struct rt_object_information *)my_addr; struct rt_object_information * t32_rt_semaphore_container = t32_rt_thread_container + 1; struct rt_object_information * t32_rt_mutex_container = t32_rt_semaphore_container + 1; struct rt_object_information * t32_rt_event_container = t32_rt_mutex_container + 1; struct rt_object_information * t32_rt_mailbox_container = t32_rt_event_container + 1; struct rt_object_information * t32_rt_messagequeue_container = t32_rt_mailbox_container + 1; struct rt_object_information * t32_rt_memheap_container = t32_rt_messagequeue_container + 1; struct rt_object_information * t32_rt_device_container = t32_rt_memheap_container + 1; struct rt_object_information * t32_rt_timer_container = t32_rt_device_container + 1; struct rt_object_information * t32_rt_module_container = t32_rt_timer_container + 1; 

通過導(dǎo)出對象容器二維數(shù)組的地址,獲取各個類型對象的列表。

比如要想獲取系統(tǒng)當(dāng)前運(yùn)行的線程相關(guān)的信息

rt_list_t* thread_list;
 thread_list = t32_rt_thread_container->object_list.next; rt_thread_t rtt_thread;
 rtt_thread = (rt_thread_t)(thread_list - 1); while (1)
 { if(rtt_thread->stack_size < 20480)
 {
 rt_kprintf("rtt_thread->name is %s\n", rtt_thread->name); switch (rtt_thread->stat)
 { case RT_THREAD_INIT:
 rt_kprintf("RT_THREAD_INIT\n"); break; case RT_THREAD_READY:
 rt_kprintf("RT_THREAD_READY\n"); break; case RT_THREAD_SUSPEND:
 rt_kprintf("RT_THREAD_SUSPEND\n"); break; case RT_THREAD_RUNNING:
 rt_kprintf("RT_THREAD_RUNNING\n"); break; case RT_THREAD_CLOSE:
 rt_kprintf("RT_THREAD_CLOSE\n"); break; default: break;
 } // rt_kprintf("rtt_thread->list is %p\n", rtt_thread->list); // rt_kprintf("rtt_thread->type is %p\n", rtt_thread->type); // rt_kprintf("rtt_thread->stack_size is %p\n", rtt_thread->stack_size); // rt_kprintf("rtt_thread->number_mask is %p\n", rtt_thread->number_mask); } else { break;
 }
 
 thread_list = thread_list->next;
 rtt_thread = (rt_thread_t)(thread_list - 1);
 }

這樣就可以解析到當(dāng)前系統(tǒng)中對象相關(guān)的信息了。其中比較重要的一個理解就是,線程鏈表其實指向的就是線程的結(jié)構(gòu)體的首地址。這樣解析起來就非常的容易了。

5.總結(jié)

通過對象容器,可以獲取系統(tǒng)信息,因為rt-thread的一切皆對象的設(shè)計思想,這種設(shè)計有很多好處。對象的管理需要相應(yīng)的容器進(jìn)行管理,這部分確實值得好好理解與學(xué)習(xí)。以后寫嵌入式代碼也需要有架構(gòu),有設(shè)計,有管理器,這樣設(shè)計出來的代碼才更加的可靠以及易于擴(kuò)展。


本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
關(guān)閉