_object_container对象容器数组
在RT-Thread操作系统中,_object_container
数组的作用是按类型分类管理内核对象,提供高效的类型检查、资源管理和统计功能
c
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
函数就理解了,这也和这个宏的名字对上了,即初始化
c
// 链表初始化 即自己指向自己
rt_inline void rt_list_init(rt_list_t *l)
{
l->next = l->prev = l;
}
rt_object_allocate(用于动态创建对象)
rt_object_allocate
为新创建的对象申请句柄内存,并将其加入到链表中
以下是动态创建线程的接口代码:
c
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
其示意代码如下:
c
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_entry
obj = 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都是一致的
c
/**
* 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. */