_object_container對象容器數組
在RT-Thread操作系統中,_object_container
數組的作用是按類型分類管理內核對象,提供高效的類型檢查、資源管理和統計功能
struct rt_list_node
{struct rt_list_node *next; /**< point to next node. */struct rt_list_node *prev; /**< point to prev node. */
};
typedef struct rt_list_node rt_list_t; /**< Type for lists. */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 */
};#define _OBJ_CONTAINER_LIST_INIT(c) \{&(_object_container[c].object_list), &(_object_container[c].object_list)}static struct rt_object_information _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)},/* initialize object container - semaphore */{RT_Object_Class_Semaphore, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Semaphore), sizeof(struct rt_semaphore)},// ......
}
從源碼可以看出,_object_container
包含了所有對象,如thread
、sem
等
_OBJ_CONTAINER_LIST_INIT
可能比較難理解,里面有兩個一模一樣的&(_object_container[c].object_list)
,乍一看rt_object_information
結構體也才3個元素,這里宏展開后一共都有4個元素了?
其實不然,_OBJ_CONTAINER_LIST_INIT
用了花括號,只代表一個元素rt_list_t object_list
,花括號里的值代表著next
和 prev
至于為什么是兩個一模一樣的值,看過rt_list_init
函數就理解了,這也和這個宏的名字對上了,即初始化
// 鏈表初始化 即自己指向自己
rt_inline void rt_list_init(rt_list_t *l)
{l->next = l->prev = l;
}
rt_object_allocate(用于動態創建對象)
rt_object_allocate
為新創建的對象申請句柄內存,并將其加入到鏈表中
以下是動態創建線程的接口代碼:
rt_thread_t rt_thread_create(const char *name, void (*entry)(void *parameter), void *parameter, rt_uint32_t stack_size,rt_uint8_t priority, rt_uint32_t tick)
{struct rt_thread *thread;void *stack_start;thread = (struct rt_thread *)rt_object_allocate(RT_Object_Class_Thread, name);stack_start = (void *)RT_KERNEL_MALLOC(stack_size);_thread_init(thread, name, entry, parameter, stack_start, stack_size, priority, tick);return thread;
}rt_object_t rt_object_allocate(enum rt_object_class_type type, const char *name)
{struct rt_object *object;rt_base_t level;struct rt_object_information *information;// 獲取對應類型對象管理結構體information = rt_object_get_information(type);// 為句柄申請空間object = (struct rt_object *)RT_KERNEL_MALLOC(information->object_size);rt_memset(object, 0x0, information->object_size);object->type = type;object->flag = 0;rt_strncpy(object->name, name, RT_NAME_MAX);// 將新創建的鏈表加入到對象管理結構體的鏈表中rt_list_insert_after(&(information->object_list), &(object->list));return object;
}
list_find_init(用于遍歷對象)
在FinSH命令行插件中,有查看對象狀態的功能,如list_thread
其示意代碼如下:
typedef struct
{rt_list_t *list;rt_list_t **array;rt_uint8_t type;int nr; // 最大個數int nr_out; // 實際個數
} list_get_next_t;static void list_find_init(list_get_next_t *p, rt_uint8_t type, rt_list_t **array, int nr)
{struct rt_object_information *info;rt_list_t *list;// 返回對應的對象管理結構體info = rt_object_get_information((enum rt_object_class_type)type);// 找到最關鍵的鏈表list = &info->object_list;p->list = list;p->type = type;p->array = array;p->nr = nr;p->nr_out = 0;
}long list_thread(void)
{list_get_next_t find_arg;rt_list_t *obj_list[LIST_FIND_OBJ_NR];rt_list_t *next = (rt_list_t *)RT_NULL;list_find_init(&find_arg, RT_Object_Class_Thread, obj_list, sizeof(obj_list) / sizeof(obj_list[0]));do{// 這里給obj_list數組賦值,里面存著每個對象的鏈表// 這里一次最多獲取LIST_FIND_OBJ_NR個對象next = list_get_next(next, &find_arg);{int i;// 循環打印對象信息for (i = 0; i < find_arg.nr_out; i++){struct rt_object *obj;struct rt_thread *thread;// 通過結構體中的元素找到結構體本身,第一章中有詳細講解rt_list_entryobj = rt_list_entry(obj_list[i], struct rt_object, list);thread = (struct rt_thread *)obj;// 打印相關信息}}} while (next != (rt_list_t *)RT_NULL);return 0;
}
rt_object 結構體
基礎的結構體,所有內核對象結構體的開頭都會定義struct rt_object parent;
但是不知道為什么rt_thread
結構體開頭把rt_object
展開了,但是效果和offset都是一致的
/*** Base structure of Kernel object*/
struct rt_object
{char name[RT_NAME_MAX]; /**< name of kernel object */rt_uint8_t type; /**< type of kernel object */rt_uint8_t flag; /**< flag of kernel object */rt_list_t list; /**< list node of kernel object */
};
typedef struct rt_object *rt_object_t; /**< Type for kernel objects. */