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. */
相关推荐
努力做小白7 分钟前
Linux驱动22 --- RV1126 环境搭建&&设备树修改
linux·驱动开发·单片机·嵌入式硬件·rv1126
阿川!19 分钟前
嵌入式软件--stm32 DAY 9 定时器
stm32·单片机·嵌入式硬件
mit6.8242 小时前
[蓝牙通信] 临界区管理 | volatile | 同步(互斥锁与信号量) | handle
c++·物联网
Promise_then2 小时前
如何在技术世界中保持清醒和高效
嵌入式·软件工程·嵌入式软件
DIY机器人工房4 小时前
【科普】STM32CubeMX是配置工具,STM32CubeIDE是集成开发环境,二者互补但定位不同,前者负责初始化配置,后者专注代码开发调试。
单片机·嵌入式硬件·嵌入式·diy机器人工房
努力做小白5 小时前
Linux驱动20 --- FFMPEG视频API
linux·驱动开发·单片机·嵌入式硬件·ffmpeg·lvgl
得单片机的运13 小时前
STM32的蓝牙通讯(HAL库)
stm32·单片机·嵌入式硬件·蓝牙
国科安芯14 小时前
抗辐照芯片在低轨卫星星座CAN总线通讯及供电系统的应用探讨
运维·网络·人工智能·单片机·自动化
jz_ddk15 小时前
[HarmonyOS] 鸿蒙LiteOS-A内核深度解析 —— 面向 IoT 与智能终端的“小而强大”内核
物联网·学习·华为·harmonyos
weixin_4526006915 小时前
GC8872刷式直流电机驱动器详解:3.6A驱动能力与PWM控制
stm32·单片机·嵌入式硬件·智能家居·音响·电动工具