RT-Thread内核笔记

RT-Thread内核笔记

基于RT-Thread 3.1.3源码分析
仅作为学习与记录之用,如有错误,欢迎指出

1、内核基础

rt-thread实时内核的实现包括:对象管理、线程管理、调度器、线程间通信管理、时钟管理、内存管理。内核最小的资源占用情况是3KB ROM,1.2KB RAM.
image-20210102164112874

2、RT-Thread内核对象模型

静态对象和动态对象

RT-Thread 系统级的基础设施都是一种内核对象,例如线程,信号量,互斥量,定时器等。内核对象分为两类:静态内核对象和动态内核对象,静态内核(rt_thread_init)对象通常放在 RW 段和 ZI 段中,在系统启动后在程序中初始化;动态内核(rt_thread_create)对象则是从内存堆中创建的,而后手工做初始化。

内核对象管理架构

RT-Thread的内核对象包括线程、信号量、互斥量、事件、邮箱、消息队列和定时器、内存池、设备驱动等。初始化后的内核对象将插入到内核对象类型的链表里。
image-20210102210631034
对象容器在代码里的体现是一个 struct rt_object_information 类型的静态数组中的元素,static struct rt_object_information rt_object_container[ ]

/* 对象容器初始化 */
/* rt-thread中,每一个类型的内核对象都有一个内核对象容器来包容,每个内核容器里有很多个对象(线程容器里有线程1 线程2...),内核对象由链表相连 */
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)},

    /* initialize object container - semaphore */
    /* 初始化信号量对象容器 */
    {RT_Object_Class_Semaphore, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Semaphore), sizeof(struct rt_semaphore)},

    /* initialize object container - mutex */
    /* 初始化互斥量对象容器 */
    {RT_Object_Class_Mutex, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Mutex), sizeof(struct rt_mutex)},

    /* initialize object container - event */
    /* 初始化事件对象容器 */
    {RT_Object_Class_Event, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Event), sizeof(struct rt_event)},

    /* initialize object container - mailbox */
    /* 初始化邮箱对象容器 */
    {RT_Object_Class_MailBox, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MailBox), sizeof(struct rt_mailbox)},

    /* initialize object container - message queue */
    /* 初始化消息队列对象容器 */
    {RT_Object_Class_MessageQueue, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MessageQueue), sizeof(struct rt_messagequeue)},

    /* initialize object container - memory heap */
    /* 初始化内存堆对象容器 */
    {RT_Object_Class_MemHeap, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MemHeap), sizeof(struct rt_memheap)},

    /* initialize object container - memory pool */
    /* 初始化内存池对象容器 */
    {RT_Object_Class_MemPool, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MemPool), sizeof(struct rt_mempool)},

    /* initialize object container - device */
    /* 初始化设备驱动对象容器 */
    {RT_Object_Class_Device, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Device), sizeof(struct rt_device)},

    /* initialize object container - timer */
    /* 初始化定时器对象容器 */
    {RT_Object_Class_Timer, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Timer), sizeof(struct rt_timer)},

    /* initialize object container - module */
    {RT_Object_Class_Module, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Module), sizeof(struct rt_dlmodule)},

};

struct rt_object_information 类型是内核对象容器的数据结构,其结构体的数据结构如下:

/**
 * 对象容器的数据结构
 */
struct rt_object_information
{
    enum rt_object_class_type type;                     /* 对象的类型 */
    rt_list_t                 object_list;              /* 对象的链表 */
    rt_size_t                 object_size;              /* 对象的大小 */
};
  • type为内核的类型,内核类型是一个枚举类型,enum rt_object_class_type;
  • object_list是链表,新创建的对象将以类型为匹配,插入到相应类型的链表的后面。在容器里,这里的链表其实是相对应内核对象链表的头节点;
  • object_size是对象的大小,此大小值与创建时的类型相关,是在容器初始化时就已经指定了的大小。

系统支持的内核对象类型如下:

enum rt_object_class_type
{
     RT_Object_Class_Thread = 0,             /* 对象为线程类型      */
#ifdef RT_USING_SEMAPHORE
    RT_Object_Class_Semaphore,              /* 对象为信号量类型    */
#endif
#ifdef RT_USING_MUTEX
    RT_Object_Class_Mutex,                  /* 对象为互斥量类型    */
#endif
#ifdef RT_USING_EVENT
    RT_Object_Class_Event,                  /* 对象为事件类型      */
#endif
#ifdef RT_USING_MAILBOX
    RT_Object_Class_MailBox,                /* 对象为邮箱类型      */
#endif
#ifdef RT_USING_MESSAGEQUEUE
    RT_Object_Class_MessageQueue,           /* 对象为消息队列类型   */
#endif
#ifdef RT_USING_MEMPOOL
    RT_Object_Class_MemPool,                /* 对象为内存池类型     */
#endif
#ifdef RT_USING_DEVICE
    RT_Object_Class_Device,                 /* 对象为设备类型       */
#endif
    RT_Object_Class_Timer,                  /* 对象为定时器类型     */
#ifdef RT_USING_MODULE
    RT_Object_Class_Module,                 /* 对象为模块          */
#endif
    RT_Object_Class_Unknown,                /* 对象类型未知        */
    RT_Object_Class_Static = 0x80           /* 对象为静态对象      */
};

对象控制块

内核对象控制块的数据结构(内核对象基类)

struct rt_object
{
    /* 注册到系统中的驱动设备名称 */
    char       name[RT_NAME_MAX]; 
    /* 驱动设备的类型 enum rt_device_class_type */                      
    rt_uint8_t type;    
    /* 驱动设备注册时指定的标志位,RT_DEVICE_FLAG_RDONLY...... */                                
    rt_uint8_t flag;                                    

#ifdef RT_USING_MODULE
    void      *module_id;                               /**< id of application module */
#endif
    rt_list_t  list;                                    /* 内核对象的链表 */
};

所有的内核对象信息均是继承于rt_object基本对象的属性,并在其基础上扩展了自己相关的属性。
*此图来源RT-THREAD官网RT-Thread 内核对象继承关系
内核对象如果是静态的对象,那么对象类型的最高位将是1(对象类型|RT_Object_Class_Static),否则就是动态对象。系统最多能够的对象类别数目是127个(0111 1111)。

源码分析

初始化对象

初始化对象用于静态对象创建。比如rt_thread_init。

/**
 * This function will initialize an object and add it to object system
 * management.
 * 将对象以指定的名字,加入到指定类型的对象管理系统中。
 * @param object the specified object to be initialized.
 * @param type the object type.
 * @param name the object name. In system, the object's name must be unique.
 */
void rt_object_init(struct rt_object         *object,
                    enum rt_object_class_type type,
                    const char               *name)
{
    register rt_base_t temp;
    struct rt_list_node *node = RT_NULL;                    /* 新建一个双向链表节点 */ 
    struct rt_object_information *information;              /* 内核对象容器 */
#ifdef RT_USING_MODULE
    struct rt_dlmodule *module = dlmodule_self();
#endif

    /* 获取当前内核对象容器 */
    /* rt-thread中,每一个类型的内核对象都有一个内核对象容器来包容 */
    /* 当前操作是从内核对象容器中,相当于寻找相应对象容器里链表的头结点 */
    information = rt_object_get_information(type);    
    /* 检查当前的对象 */ 
    /* 如果当前对象为空,说明内核容器表里没有这个类型的内核容器 */     
    RT_ASSERT(information != RT_NULL);

    /* 进入临界区 */
    rt_enter_critical();                                    
    /* try to find object */
    /* 寻找对象容器里,是否存在当前要新建的对象 */
    for (node  = information->object_list.next;
            node != &(information->object_list);
            node  = node->next)
    {
        struct rt_object *obj;

        /* 根据节点找到struct rt_object结构体的首地址,如果这个首地址与传入的结构体首地址相同,则说明这个结构体已经被插入到链表里了 */
        obj = rt_list_entry(node, struct rt_object, list);
        /* 如果当前要新建的对象已经存在,则会触发断言 */
        RT_ASSERT(obj != object);
    }
    /* 离开临界区 */
    rt_exit_critical();

    /* initialize object's parameters */
    /* set object type to static */
    /* 此函数适用于静态创建的对象,将type加上静态,主要是在对象删除(rt_object_delete)时用于判断 */
    object->type = type | RT_Object_Class_Static;
    /* copy name */
    rt_strncpy(object->name, name, RT_NAME_MAX);

    RT_OBJECT_HOOK_CALL(rt_object_attach_hook, (object));

    /* 关闭中断使能 */
    temp = rt_hw_interrupt_disable();   

#ifdef RT_USING_MODULE
    if (module)
    {
        rt_list_insert_after(&(module->object_list), &(object->list));
        object->module_id = (void *)module;
    }
    else
#endif
    {
        /* 将对象插入到对应类型的内核容器中的链表里 */
        rt_list_insert_after(&(information->object_list), &(object->list));
    }

    /* 重新打开中断使能 */
    rt_hw_interrupt_enable(temp);       
}

image-20210102192736987

脱离对象

脱离对象针对的是静态创建的对象。

/**
 * This function will detach a static object from object system,
 * and the memory of static object is not freed.
 * 将对象脱离对象容器链表
 * @param object the specified object to be detached.
 */
void rt_object_detach(rt_object_t object)
{
    register rt_base_t temp;

    /* object check */
    RT_ASSERT(object != RT_NULL);

    RT_OBJECT_HOOK_CALL(rt_object_detach_hook, (object));

    /* reset object type */
    object->type = 0;

    /* lock interrupt */
    temp = rt_hw_interrupt_disable();

    /* remove from old list */
    /* 从链表中移除对象 */
    rt_list_remove(&(object->list));

    /* unlock interrupt */
    rt_hw_interrupt_enable(temp);
}

初始化对象时,将对象插入到对象容器的链表里了,脱离操作就是从链表里,去除节点。

分配对象

分配对象是动态创建的对象。在动态内存堆中申请空间来创建对象。

/**
 * This function will allocate an object from object system
 * 分配对象。为动态创建的对象分配内存空间
 * @param type the type of object
 * @param name the object name. In system, the object's name must be unique.
 *
 * @return object
 */
rt_object_t rt_object_allocate(enum rt_object_class_type type, const char *name)
{
    struct rt_object *object;
    register rt_base_t temp;
    struct rt_object_information *information;
#ifdef RT_USING_MODULE
    struct rt_dlmodule *module = dlmodule_self();
#endif

    RT_DEBUG_NOT_IN_INTERRUPT;

    /* get object information */
    /* 寻找对象容器,其实就是寻找对象链表的头节点 */
    information = rt_object_get_information(type);
    RT_ASSERT(information != RT_NULL);

    /* 为对象申请内存空间 */
    object = (struct rt_object *)RT_KERNEL_MALLOC(information->object_size);
    if (object == RT_NULL)
    {
        /* no memory can be allocated */
        return RT_NULL;
    }

    /* clean memory data of object */
    /* 并且初始化内存空间 */
    rt_memset(object, 0x0, information->object_size);

    /* initialize object's parameters */

    /* set object type */
    object->type = type;

    /* set object flag */
    object->flag = 0;

    /* copy name */
    rt_strncpy(object->name, name, RT_NAME_MAX);

    RT_OBJECT_HOOK_CALL(rt_object_attach_hook, (object));

    /* lock interrupt */
    temp = rt_hw_interrupt_disable();

#ifdef RT_USING_MODULE
    if (module)
    {
        rt_list_insert_after(&(module->object_list), &(object->list));
        object->module_id = (void *)module;
    }
    else
#endif
    {
        /* insert object into information object list */
        /* 将申请好的对象节点插入到内核对象链表中 */
        rt_list_insert_after(&(information->object_list), &(object->list));
    }

    /* unlock interrupt */
    rt_hw_interrupt_enable(temp);

    /* return object */
    return object;
}

image-20210102204131445

删除对象

删除对象适用于动态创建的对象。

其函数是执行判断当前的对象类型为非静态创建的对象,然后从容器链表里移除当前的节点,最后释放掉动态内存。

/**
 * This function will delete an object and release object memory.
 * 内核对象删除且释放内存空间
 * @param object the specified object to be deleted.
 */
void rt_object_delete(rt_object_t object)
{
    register rt_base_t temp;

    /* object check */
    RT_ASSERT(object != RT_NULL);
    RT_ASSERT(!(object->type & RT_Object_Class_Static));

    RT_OBJECT_HOOK_CALL(rt_object_detach_hook, (object));

    /* reset object type */
    object->type = 0;

    /* lock interrupt */
    temp = rt_hw_interrupt_disable();

    /* remove from old list */
    rt_list_remove(&(object->list));

    /* unlock interrupt */
    rt_hw_interrupt_enable(temp);

    /* free the memory of object */
    RT_KERNEL_FREE(object);
}
辨别对象

判断指定的对象是否为系统对象(静态内核对象,RT_Object_Class_Static )

/**
 * This function will judge the object is system object or not.
 * Normally, the system object is a static object and the type
 * of object set to RT_Object_Class_Static.
 * 该函数用来判断对象是否是系统对象。系统对象是静态对象,type是RT_Object_Class_Static
 *
 * @param object the specified object to be judged.
 *
 * @return RT_TRUE if a system object, RT_FALSE for others.
 */
rt_bool_t rt_object_is_systemobject(rt_object_t object)
{
    /* object check */
    RT_ASSERT(object != RT_NULL);

    if (object->type & RT_Object_Class_Static)
        return RT_TRUE;

    return RT_FALSE;
}
获取对象类型
/**
 * This function will return the type of object without
 * RT_Object_Class_Static flag.
 * 此函数用来获取当前的对象类型。
 *
 * @param object the specified object to be get type.
 *
 * @return the type of object.
 */
rt_uint8_t rt_object_get_type(rt_object_t object)
{
    /* object check */
    RT_ASSERT(object != RT_NULL);

    /* 置RT_Object_Class_Static位的是静态变量,type为8位的数据类型 */
    return object->type & ~RT_Object_Class_Static;
}
寻找指定名称的类型对象
/**
 * This function will find specified name object from object
 * container.
 * 此函数会从对象容器中寻找指定名字的对象
 *
 * @param name the specified name of object.
 * @param type the type of object
 *
 * @return the found object or RT_NULL if there is no this object
 * in object container.
 *
 * @note this function shall not be invoked in interrupt status.
 */
rt_object_t rt_object_find(const char *name, rt_uint8_t type)
{
    struct rt_object *object = RT_NULL;
    struct rt_list_node *node = RT_NULL;
    struct rt_object_information *information = RT_NULL;

    /* parameter check */
    /* 参数检查,判断名字为非空,且类型是所有类型里的 */
    if ((name == RT_NULL) || (type > RT_Object_Class_Unknown))
        return RT_NULL;

    /* which is invoke in interrupt status */
    RT_DEBUG_NOT_IN_INTERRUPT;

    /* enter critical */
    rt_enter_critical();

    /* try to find object */
    if (information == RT_NULL)
    {
        /* 首先,先找到对应类型的对象容器的指针,也就是对象类型链表的头节点 */
        information = rt_object_get_information((enum rt_object_class_type)type);
        RT_ASSERT(information != RT_NULL);
    }
    /* 然后遍历类型对象链表,找到匹配的名称,然后返回对象的指针 */
    for (node  = information->object_list.next;
            node != &(information->object_list);
            node  = node->next)
    {
        /* 此处的node其实指向object->list */
        object = rt_list_entry(node, struct rt_object, list);
        if (rt_strncmp(object->name, name, RT_NAME_MAX) == 0)
        {
            /* leave critical */
            rt_exit_critical();

            return object;
        }
    }

    /* leave critical */
    rt_exit_critical();

    return RT_NULL;
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值