内核 3-对象模型

目录

1、对象

1.1、继承关系

1.2、静态对象和动态对象

1.3、rt_object_class_type枚举类型(对象类型)

1.3.1、RT_Object_Class_Static作用 

1.4、rt_object结构体(对象结构体)

1.4.1、对象flags说明

2、对象容器

2.1、rt_object_info_type枚举

2.1.1、RT_Object_Info_Unknown作用

2.2、rt_object_information结构体(对象信息)

2.3、rt_object_container结构体

2.3.1、RT_USING_XXX宏

2.3.2、_OBJ_CONTAINER_LIST_INIT宏

3、函数

3.1、rt_object_init()函数

3.2、rt_object_allocate()函数

3.3、rt_object_detach()函数

3.4、rt_object_delete()函数

3.5、rt_object_is_systemobject()函数

3.6、rt_object_get_type()函数

3.7、rt_object_get_information()函数

3.8、rt_object_find()函数

3.9、rt_object_get_length()函数

3.10、rt_object_get_pointers()函数

4、IPC对象

4.1、IPC控制块

4.2、函数

4.2.1、rt_ipc_object_init()函数

4.2.2、rt_ipc_list_resume()函数

4.2.3、rt_ipc_list_resume_all()函数

4.2.4、rt_ipc_list_suspend()函数


1、对象

RT-Thread 内核采用面向对象的设计思想进行设计,系统级的基础设施都是一种内核对象,例如线程,信号量,互斥量,定时器等。

1.1、继承关系

从面向对象的观点,可以认为每一种具体对象是抽象对象的派生,继承了基本对象的属性并在此基础上扩展了与自己相关的属性。

1.2、静态对象和动态对象

内核对象分为两类:静态内核对象和动态内核对象。静态对象会占用 RAM 空间,不依赖于内存堆管理器,内存分配时间确定。动态对象则依赖于内存堆管理器,运行时申请 RAM 空间,当对象被删除后,占用的 RAM 空间被释放。

静态对象标识对象是静态的(存放在数据段)。
动态对象标识对象是从堆中分配的,不需要时需要释放!

1.3、rt_object_class_type枚举类型(对象类型)

enum rt_object_class_type
{
    RT_Object_Class_Null   = 0,                         /* 未使用 */
    RT_Object_Class_Thread,                             /* 线程 */
    RT_Object_Class_Semaphore,                          /* 信号量*/
    RT_Object_Class_Mutex,                              /* 互斥量 */
    RT_Object_Class_Event,                              /* 事件 */
    RT_Object_Class_MailBox,                            /* 邮箱 */
    RT_Object_Class_MessageQueue,                       /* 消息队列 */
    RT_Object_Class_MemHeap,                            /* 内存堆 */
    RT_Object_Class_MemPool,                            /* 内存池 */
    RT_Object_Class_Device,                             /* 设备 */
    RT_Object_Class_Timer,                              /* 定时器 */
    RT_Object_Class_Module,                             /* 模块 */
    RT_Object_Class_Unknown,                            /* 未知 */
    RT_Object_Class_Static = 0x80                       /* 静态对象 */
};

1.3.1、RT_Object_Class_Static作用 

RT_Object_Class_Static 用于标识对象是静态对象。

注:如果是静态对象,那么对象类型的最高位将是1(是RT_Object_Class_Static 与其他对象类型的与操作),否则就是动态对象,系统最多能够容纳的对象类别数目是 127 个。

1.4、rt_object结构体(对象结构体)

rt_object是内核对象的基础结构体,所有的对象均使用到此结构体。

//对象结构体
struct rt_object
{
    char       name[RT_NAME_MAX];                       /* 对象名字 */
    rt_uint8_t type;                                    /* 对象类型 */
    rt_uint8_t flag;                                    /* 对象标志 */

    rt_list_t  list;                                    /* 对象链表 */
};
typedef struct rt_object *rt_object_t;                  /* 类型定义rt_object_t */

信号量、互斥量、事件、邮箱、消息队列、内存堆、内存池、设备、定时器的结构体中均有parent成员(类型为struct rt_object)。

线程对象的结构体中虽然没有类型为struct rt_ipc_object的成员。但其结构体的前面部分,其成员类型与struct rt_ipc_object的成员类型完全一致!

struct rt_thread
{
    char        name[RT_NAME_MAX];                      
    rt_uint8_t  type;                                  
    rt_uint8_t  flags;                                  

    rt_list_t   list;                                  
    ...
}

1.4.1、对象flags说明

flags根据对象的不同而意义不同!

内核对象标志说明
信号量、互斥量、事件集、邮箱、消息队列RT_IPC_FLAG_FIFO

采用先进先出策略

RT_IPC_FLAG_PRIO采用优先级策略
定时器RT_TIMER_FLAG_ONE_SHOT单次定时
RT_TIMER_FLAG_PERIODIC周期定时
RT_TIMER_FLAG_ACTIVATED定时器激活
RT_TIMER_FLAG_DEACTIVATED定时器未激活

2、对象容器

2.1、rt_object_info_type枚举

enum rt_object_info_type
{
    RT_Object_Info_Thread = 0,                         /**< The object is a thread. */
#ifdef RT_USING_SEMAPHORE
    RT_Object_Info_Semaphore,                          /**< The object is a semaphore. */
#endif
#ifdef RT_USING_MUTEX
    RT_Object_Info_Mutex,                              /**< The object is a mutex. */
#endif
#ifdef RT_USING_EVENT
    RT_Object_Info_Event,                              /**< The object is a event. */
#endif
#ifdef RT_USING_MAILBOX
    RT_Object_Info_MailBox,                            /**< The object is a mail box. */
#endif
#ifdef RT_USING_MESSAGEQUEUE
    RT_Object_Info_MessageQueue,                       /**< The object is a message queue. */
#endif
#ifdef RT_USING_MEMHEAP
    RT_Object_Info_MemHeap,                            /**< The object is a memory heap */
#endif
#ifdef RT_USING_MEMPOOL
    RT_Object_Info_MemPool,                            /**< The object is a memory pool. */
#endif
#ifdef RT_USING_DEVICE
    RT_Object_Info_Device,                             /**< The object is a device */
#endif
    RT_Object_Info_Timer,                              /**< The object is a timer. */
    RT_Object_Info_Unknown,                            /**< The object is unknown. */
}

2.1.1、RT_Object_Info_Unknown作用

用于灵活定义对象容器的大小。

static struct rt_object_information rt_object_container[RT_Object_Info_Unknown]

2.2、rt_object_information结构体(对象信息)

struct rt_object_information
{
	enum rt_object_class_type type;                     /* 对象类型 */
	rt_list_t                 object_list;              /* 对象链表 */
	rt_size_t                 object_size;              /* 对象类型大小 */
};

一类对象由一个 rt_object_information 结构体来管理。每一个这类对象的具体实例都通过链表节点object_list的形式挂接在相应的对象链表上(例如线程对象挂到线程链表上、信号量对象挂到信号量链表上等)。而这一类对象的内存块尺寸由 object_size 标识出来(每一类对象的具体实例,他们占有的内存块大小都是相同的)。

2.3、rt_object_container结构体

Rt-Thread的对象都是通过对象容器进行管理。

static struct rt_object_information rt_object_container[RT_Object_Info_Unknown] =
{
    //初始化线程对象容器
    {RT_Object_Class_Thread, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Thread), sizeof(struct rt_thread)},
#ifdef RT_USING_SEMAPHORE
    //初始化信号量对象容器
    {RT_Object_Class_Semaphore, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Semaphore), sizeof(struct rt_semaphore)},
#endif
#ifdef RT_USING_MUTEX
   //初始化互斥量对象容器
    {RT_Object_Class_Mutex, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Mutex), sizeof(struct rt_mutex)},
#endif
#ifdef RT_USING_EVENT
    //初始化事件对象容器
    {RT_Object_Class_Event, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Event), sizeof(struct rt_event)},
#endif
#ifdef RT_USING_MAILBOX
    //初始化邮箱对象容器
    {RT_Object_Class_MailBox, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MailBox), sizeof(struct rt_mailbox)},
#endif
#ifdef RT_USING_MESSAGEQUEUE
   //初始化消息队列对象容器
    {RT_Object_Class_MessageQueue, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MessageQueue), sizeof(struct rt_messagequeue)},
#endif
#ifdef RT_USING_MEMHEAP
    //初始化内存堆对象容器
    {RT_Object_Class_MemHeap, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MemHeap), sizeof(struct rt_memheap)},
#endif
#ifdef RT_USING_MEMPOOL
    //初始化内存池对象容器
    {RT_Object_Class_MemPool, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MemPool), sizeof(struct rt_mempool)},
#endif
#ifdef RT_USING_DEVICE
    //初始化设备对象容器
    {RT_Object_Class_Device, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Device), sizeof(struct rt_device)},
#endif
    //初始化定时器对象容器
    {RT_Object_Class_Timer, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Timer), sizeof(struct rt_timer)},
#ifdef RT_USING_MODULE
    //初始化模块对象容器
    {RT_Object_Class_Module, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Module), sizeof(struct rt_dlmodule)},
#endif
};

2.3.1、RT_USING_XXX宏

RT-thread是可裁剪的。定义相应宏开启相应功能。

说明
RT_USING_SEMAPHORE使用信号量
RT_USING_MUTEX使用互斥量
RT_USING_EVENT使用事件
RT_USING_MAILBOX使用邮箱
RT_USING_MESSAGEQUEUE使用队列
RT_USING_MEMHEAP使用内存堆
RT_USING_MEMPOOL使用内存池
RT_USING_DEVICE使用设备
RT_USING_MODULE使用模块

2.3.2、_OBJ_CONTAINER_LIST_INIT宏

_OBJ_CONTAINER_LIST_INIT宏的作用是初始化对象容器的object_list成员链表(将object_list的prev成员和next成员设置为object_list的地址)。

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)     \
    {&(rt_object_container[c].object_list), &(rt_object_container[c].object_list)}

3、函数

3.1、rt_object_init()函数

此函数将初始化一个对象并将其添加到对象容器中。

1)设置object的类型(并标识静态类型)和object的名称

2)调用钩子回调

3)将object插入到类型为type的对象链表中。

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; 

    information = rt_object_get_information(type); //获取对象信息
    RT_ASSERT(information != RT_NULL); //断言information != RT_NULL

    rt_enter_critical(); //进入临界区

    //寻找对象,仅用于断言此对象未在对象容器中
    for (node  = information->object_list.next;
            node != &(information->object_list);
            node  = node->next)
    {
        struct rt_object *obj;

        obj = rt_list_entry(node, struct rt_object, list); //获取对象
        RT_ASSERT(obj != object); //断言obj != object
    }

    rt_exit_critical(); //离开临界区

    //初始化对象参数,并设置对象类型为静态类型
    object->type = type | RT_Object_Class_Static;

    rt_strncpy(object->name, name, RT_NAME_MAX); //设置名字

    RT_OBJECT_HOOK_CALL(rt_object_attach_hook, (object)); //调用回调

    temp = rt_hw_interrupt_disable(); //关中断

    {
        
        rt_list_insert_after(&(information->object_list), &(object->list)); // 将对象插入对象信息链表
    }

    rt_hw_interrupt_enable(temp); //开中断
}

3.2、rt_object_allocate()函数

此函数功能与rt_object_init()函数差不多,都是初始化一个对象并将其添加到对象容器中。不过rt_object_init()函数初始化的对象是静态的。rt_object_allocate()函数初始化的对象是动态的

1)分配object内存,并初始化

2)设置object的类型和object的名称

3)调用钩子回调

4)将object插入到类型为type的对象链表中。

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;

    RT_DEBUG_NOT_IN_INTERRUPT; //断言该函数不在ISR中调用

    information = rt_object_get_information(type); //获取对象信息
    RT_ASSERT(information != RT_NULL); //断言information != RT_NULL

    object = (struct rt_object *)RT_KERNEL_MALLOC(information->object_size); //分配内存
    if (object == RT_NULL) //从分配内存失败
    {
        return RT_NULL; //返回RT_NULL
    }

    rt_memset(object, 0x0, information->object_size); //清0

    object->type = type; //设置对象类型

    object->flag = 0; //设置对象标志为0

    rt_strncpy(object->name, name, RT_NAME_MAX); //设置对象名字

    RT_OBJECT_HOOK_CALL(rt_object_attach_hook, (object)); //调用回调

    temp = rt_hw_interrupt_disable(); //关中断

    {
        rt_list_insert_after(&(information->object_list), &(object->list)); //将对象插入到对象信息链表
    }

    rt_hw_interrupt_enable(temp); //关中断

    return object; //返回对象
}

3.3、rt_object_detach()函数

此函数将从对象容器中脱离一个静态对象。

1)调用钩子函数

2)从相应对象链表中移除此对象

void rt_object_detach(rt_object_t object)
{
	register rt_base_t temp;

	RT_ASSERT(object != RT_NULL); //断言object != RT_NULL

	RT_OBJECT_HOOK_CALL(rt_object_detach_hook, (object)); //调用回调

	object->type = 0; //复位对象类型

	temp = rt_hw_interrupt_disable(); //关中断

	rt_list_remove(&(object->list)); //从对象信息链表中移除

	rt_hw_interrupt_enable(temp); //开中断
}

3.4、rt_object_delete()函数

此函数将删除一个动态对象并释放对象内存。

1)调用钩子函数

2)从相应对象链表中移除此对象

3)释放对象内存

void rt_object_delete(rt_object_t object)
{
	register rt_base_t temp;

	RT_ASSERT(object != RT_NULL); //断言object != RT_NULL
	RT_ASSERT(!(object->type & RT_Object_Class_Static)); //断言对象不是静态对象

	RT_OBJECT_HOOK_CALL(rt_object_detach_hook, (object)); //调用回调

	object->type = 0; //复位对象类型

	temp = rt_hw_interrupt_disable(); //关中断

	rt_list_remove(&(object->list)); //从对象信息链表中移除

	rt_hw_interrupt_enable(temp); //开中断

	RT_KERNEL_FREE(object); //释放对象内存
}

3.5、rt_object_is_systemobject()函数

判断对象是否是静态对象(根据对象类型是否与上RT_Object_Class_Static判断)。

rt_bool_t rt_object_is_systemobject(rt_object_t object)
{
	RT_ASSERT(object != RT_NULL); //断言object != RT_NULL

	if (object->type & RT_Object_Class_Static) //判断是否是静态对象
		return RT_TRUE; //返回RT_TRUE

	return RT_FALSE; //返回RT_FALSE
}

3.6、rt_object_get_type()函数

此函数用于获取对象类型。

rt_uint8_t rt_object_get_type(rt_object_t object)
{
	RT_ASSERT(object != RT_NULL); //断言object != RT_NULL

	return object->type & ~RT_Object_Class_Static; //返回对象类型
}

3.7、rt_object_get_information()函数

此函数用于根据对象类型获取对象信息。

struct rt_object_information *
rt_object_get_information(enum rt_object_class_type type)
{
	int index;

	for (index = 0; index < RT_Object_Info_Unknown; index ++) //遍历对象容器
		if (rt_object_container[index].type == type) return &rt_object_container[index]; //返回对应类型的对象信息

	return RT_NULL; //返回RT_NULL
}

3.8、rt_object_find()函数

此函数用于查找指定名称的对象。

1)根据对象类型获取对象信息。

2)遍历对象链表,并比较名称

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;

    /* 参数检查 */
	if ((name == RT_NULL) || (type > RT_Object_Class_Unknown))
		return RT_NULL; //返回RT_NULL

	RT_DEBUG_NOT_IN_INTERRUPT; //断言不在ISR中调用

	rt_enter_critical(); //进入临界区

	if (information == RT_NULL) //信息对象为空
	{
		information = rt_object_get_information((enum rt_object_class_type)type); //查找对象信息
		RT_ASSERT(information != RT_NULL); //断言information != RT_NULL
	}
    /* 从信息对象链表中遍历 */
	for (node  = information->object_list.next;
	        node != &(information->object_list);
	        node  = node->next)
	{
	    object = rt_list_entry(node, struct rt_object, list); //获取对象
	    if (rt_strncmp(object->name, name, RT_NAME_MAX) == 0) //通过比对名字查找
	    {
	        rt_exit_critical(); //离开临界区

	        return object; //返回对象
	    }
	}

	rt_exit_critical(); //离开临界区

	return RT_NULL; //返回RT_NULL
}

3.9、rt_object_get_length()函数

此函数用于获取指定类型对象的数量。

int rt_object_get_length(enum rt_object_class_type type)
{
    int count = 0;
    rt_ubase_t level;
    struct rt_list_node *node = RT_NULL;
    struct rt_object_information *information = RT_NULL;

    information = rt_object_get_information((enum rt_object_class_type)type);
    if (information == RT_NULL) return 0;

    level = rt_hw_interrupt_disable(); //关中断
    /* 获取对象的数量 */
    rt_list_for_each(node, &(information->object_list))
    {
        count ++; 
    }
    rt_hw_interrupt_enable(level); //开中断

    return count;
}

3.10、rt_object_get_pointers()函数

此函数将复制指定类型的对象指针,其最大长度由maxlen指定。

int rt_object_get_pointers(enum rt_object_class_type type, rt_object_t *pointers, int maxlen)
{
    int index = 0;
    rt_ubase_t level;

    struct rt_object *object;
    struct rt_list_node *node = RT_NULL;
    struct rt_object_information *information = RT_NULL;

    if (maxlen <= 0) return 0;

    information = rt_object_get_information((enum rt_object_class_type)type);
    if (information == RT_NULL) return 0;

    level = rt_hw_interrupt_disable(); //关中断
    /* 遍历对象指针 */
    rt_list_for_each(node, &(information->object_list))
    {
        object = rt_list_entry(node, struct rt_object, list);

        pointers[index] = object; 
        index ++;

        if (index >= maxlen) break;
    }
    rt_hw_interrupt_enable(level); //开中断

    return index;
}

4、IPC对象

Rt-Thread中IPC对象有信号量,互斥量,事件集,邮箱,消息队列。

4.1、IPC控制块

IPC控制块由rt_object继承而来。并且拥有一个线程等待链表,用于保存因获取不到资源而挂起的线程。

struct rt_ipc_object
{
    struct rt_object parent;                            /* 对象 */

    rt_list_t        suspend_thread;                    /* 线程挂起链表 */
};

4.2、函数

4.2.1、rt_ipc_object_init()函数

此函数用于初始化ipc对象。

rt_inline rt_err_t rt_ipc_object_init(struct rt_ipc_object *ipc)
{
    rt_list_init(&(ipc->suspend_thread)); //初始化ipc的线程挂起链表

    return RT_EOK; //返回RT_EOK
}

4.2.2、rt_ipc_list_resume()函数

此函数用于唤醒一个因获取不到IPC对象资源而挂起的线程。

1)根据链表节点获取要唤醒的线程控制块

2)唤醒线程

rt_inline rt_err_t rt_ipc_list_resume(rt_list_t *list)
{
    struct rt_thread *thread;

    thread = rt_list_entry(list->next, struct rt_thread, tlist); //获取线程

    RT_DEBUG_LOG(RT_DEBUG_IPC, ("resume thread:%s\n", thread->name)); //打印信息

    rt_thread_resume(thread); //唤醒线程

    return RT_EOK; //返回RT_EOK
}

4.2.3、rt_ipc_list_resume_all()函数

此函数用于唤醒因获取不到IPC对象资源而挂起的所有线程,且将线程错误码设置为RT_ERROR。

1)对因获取不到IPC对象资源而挂起的所有线程进行操作

2)将线程错误码设置为RT_ERROR

3)唤醒线程

rt_inline rt_err_t rt_ipc_list_resume_all(rt_list_t *list)
{
    struct rt_thread *thread;
    register rt_ubase_t temp;

    /* 唤醒所有挂起的线程 */
    while (!rt_list_isempty(list)) 
    {
        temp = rt_hw_interrupt_disable(); //关中断

        thread = rt_list_entry(list->next, struct rt_thread, tlist); //获取下一个挂起的线程

        thread->error = -RT_ERROR; //将线程错误码设置为RT_ERROR

        rt_thread_resume(thread); //唤醒线程

        rt_hw_interrupt_enable(temp); //开中断
    }

    return RT_EOK; //返回RT_EOK
}

4.2.4、rt_ipc_list_suspend()函数

此函数将挂起一个线程到指定的列表。

1)挂起线程

2)如果flag为RT_IPC_FLAG_FIFO,将当前线程放到挂起线程链表的最后。

3)如果flag为RT_IPC_FLAG_PRIO,根据优先级在挂起链表list中查找合适的位置插入。

rt_inline rt_err_t rt_ipc_list_suspend(rt_list_t        *list,
                                       struct rt_thread *thread,
                                       rt_uint8_t        flag)
{
    rt_thread_suspend(thread); //挂起线程

    switch (flag)
    {
    case RT_IPC_FLAG_FIFO: //根据先进先出
        rt_list_insert_before(list, &(thread->tlist)); //将当前线程放到挂起线程链表的最后
        break;

    case RT_IPC_FLAG_PRIO: //根据优先级
        {
            struct rt_list_node *n;
            struct rt_thread *sthread;

            /* 根据优先级查找合适的位置 */
            for (n = list->next; n != list; n = n->next)
            {
                sthread = rt_list_entry(n, struct rt_thread, tlist); //获取线程

                if (thread->current_priority < sthread->current_priority) //优先级比较
                {
                    /* 在sthread线程前插入此线程 */
                    rt_list_insert_before(&(sthread->tlist), &(thread->tlist)); //插入
                    break;
                }
            }

            /* 没有找到合适的位置 */
            if (n == list)
                rt_list_insert_before(list, &(thread->tlist)); //将当前线程放到挂起线程链表的最后
        }
        break;
    }

    return RT_EOK; //返回RT_EOK
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值