RT-Thread源码阅读(3)——内核对象管理

_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包含了所有对象,如threadsem

_OBJ_CONTAINER_LIST_INIT可能比较难理解,里面有两个一模一样的&(_object_container[c].object_list),乍一看rt_object_information结构体也才3个元素,这里宏展开后一共都有4个元素了?

其实不然,_OBJ_CONTAINER_LIST_INIT用了花括号,只代表一个元素rt_list_t object_list,花括号里的值代表着nextprev

至于为什么是两个一模一样的值,看过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. */
相关推荐
闻道且行之3 小时前
嵌入式|VNC实现开发板远程Debian桌面
运维·debian·嵌入式
scilwb6 小时前
RoboCon考核题——scilwb
单片机
点灯小铭7 小时前
基于STM32单片机智能RFID刷卡汽车位锁桩设计
stm32·单片机·汽车·毕业设计·课程设计
TDengine (老段)8 小时前
TDengine IDMP 高级功能(4. 元素引用)
大数据·数据库·人工智能·物联网·数据分析·时序数据库·tdengine
bai5459368 小时前
STM32 软件I2C读写MPU6050
stm32·单片机·嵌入式硬件
逼子格10 小时前
AT89C52单片机介绍
单片机·嵌入式硬件·51单片机·硬件工程师·硬件工程师真题·at89c52·器件手册
David WangYang13 小时前
基于 IOT 的安全系统,带有使用 ESP8266 的语音消息
物联网·安全·语音识别
竹照煜_ysn15 小时前
STM32——软硬件I2C
stm32·嵌入式硬件·mongodb
Wallace Zhang17 小时前
STM32 - Embedded IDE - GCC - 显著减少固件的体积
stm32·单片机·嵌入式硬件
fengfuyao9851 天前
STM32如何定位HardFault错误,一种实用方法
stm32·单片机·嵌入式硬件