中级篇_04_对象容器的实现

对象枚举定义

**
 *  The object type can be one of the follows with specific
 *  macros enabled:
 *  - Thread
 *  - Semaphore
 *  - Mutex
 *  - Event
 *  - MailBox
 *  - MessageQueue
 *  - MemHeap
 *  - MemPool
 *  - Device
 *  - Timer
 *  - Module
 *  - Unknown
 *  - Static
 */
enum rt_object_class_type
{
    RT_Object_Class_Thread = 0,                         /**< The object is a thread. */
    RT_Object_Class_Semaphore,                          /**< The object is a semaphore. */
    RT_Object_Class_Mutex,                              /**< The object is a mutex. */
    RT_Object_Class_Event,                              /**< The object is a event. */
    RT_Object_Class_MailBox,                            /**< The object is a mail box. */
    RT_Object_Class_MessageQueue,                       /**< The object is a message queue. */
    RT_Object_Class_MemHeap,                            /**< The object is a memory heap */
    RT_Object_Class_MemPool,                            /**< The object is a memory pool. */
    RT_Object_Class_Device,                             /**< The object is a device */
    RT_Object_Class_Timer,                              /**< The object is a timer. */
    RT_Object_Class_Module,                             /**< The object is a module. */
    RT_Object_Class_Unknown,                            /**< The object is unknown. */
    RT_Object_Class_Static = 0x80                       /**< The object is a static object. */
};

  对象类型的枚举定义就如上面的一般,线程,信号量···这些全部使用rt_object_class_type的枚举类型来表示。这里是即将开启对象容器的第一步,对象容器使用来管理这些数据类型,书里说利用finsh组件时候,就会扫描容器内的内核对象。

list_thread
thread pri  status      sp     stack size max used left tick  error
------ ---  ------- ---------- ----------  ------  ---------- ---
tshell  20  ready   0x00000080 0x00001000    09%   0x00000006 000
tidle   31  ready   0x00000054 0x00000100    35%   0x0000000b 000
msh >list_device
device         type         ref count
------ -------------------- ----------
uart1  Character Device     2       
pin    Miscellaneous Device 0       
msh >list_sem
semaphore v   suspend thread
-------- --- --------------
shrx     000 0
heap     001 0
msh >

  至少我在第一次使用的时候,是十分惊讶的,以为那么高级的功能只有Windows和Linux这种大型系统才能使用。

容器的定义

  当然,只是对对象类型的格式定义还不能做什么,虽然每个对象都有自己的编号但实际上,如果需要管理还需要加入容器,容器的实现在RT-Thread中是一个二维数组实现的。这个数组的名字是rt_object_container[RT_Object_container[RT_Object_Info_Unknow],它是一个二维数组,你可以理解每一个对象是行元素,对象中每一个元素是列元素。每一行列元素内包含什么信息呢?

/**
 * The information of the kernel object
 */
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 */
};

  现在就可以看这个容器的样子了,样子是这样的

tatic 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)},
#ifdef RT_USING_SEMAPHORE
    /* initialize object container - semaphore */
    {RT_Object_Class_Semaphore, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Semaphore), sizeof(struct rt_semaphore)},
#endif
#ifdef RT_USING_MUTEX
    /* initialize object container - mutex */
    {RT_Object_Class_Mutex, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Mutex), sizeof(struct rt_mutex)},
#endif
#ifdef RT_USING_EVENT
    /* initialize object container - event */
    {RT_Object_Class_Event, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Event), sizeof(struct rt_event)},
#endif
#ifdef RT_USING_MAILBOX
    /* initialize object container - mailbox */
    {RT_Object_Class_MailBox, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MailBox), sizeof(struct rt_mailbox)},
#endif
#ifdef RT_USING_MESSAGEQUEUE
    /* initialize object container - message queue */
    {RT_Object_Class_MessageQueue, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MessageQueue), sizeof(struct rt_messagequeue)},
#endif
#ifdef RT_USING_MEMHEAP
    /* initialize object container - memory heap */
    {RT_Object_Class_MemHeap, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MemHeap), sizeof(struct rt_memheap)},
#endif
#ifdef RT_USING_MEMPOOL
    /* initialize object container - memory pool */
    {RT_Object_Class_MemPool, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MemPool), sizeof(struct rt_mempool)},
#endif
#ifdef RT_USING_DEVICE
    /* initialize object container - device */
    {RT_Object_Class_Device, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Device), sizeof(struct rt_device)},
#endif
    /* initialize object container - timer */
    {RT_Object_Class_Timer, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Timer), sizeof(struct rt_timer)},
#ifdef RT_USING_MODULE
    /* initialize object container - module */
    {RT_Object_Class_Module, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Module), sizeof(struct rt_dlmodule)},
#endif
};

  里面除了RT_Object_Class_Timer和RT_Object_Class_Thread之外,全部是有条件编译限制的,可以理解为Thread和Timer是RT-Tread中不可或缺的部分,也就是可以理解为其他的部分,并不是必选项,这个容器的大小是可以变化的。容器的大小就由RT_Object_Info_Unknow来决定。哪谁来决定RT_Object_Info_Unknow的大小呢?

/*
 * define object_info for the number of rt_object_container items.
 */
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. */
#ifdef RT_USING_MODULE
    RT_Object_Info_Module,                             /**< The object is a module. */
#endif
    RT_Object_Info_Unknown,                            /**< The object is unknown. */
};

  从这里我们可以知道RT-Object_Info_Unknow的大小就是由宏定义开启多少功能来决定的。所以说,RT_Object_Info_Unknown的大小最小为2,最大为12。
  类似于优先级列表的实现,优先级利用一个长度为RT_THREAD_PRIORITY_MAX的一维数组就为我们分开了优先级不同的线程在各自的优先级链表里。容器的实现是一个二维数组。他的样子更像是这样:
容器的样子

容器接口的实现

  object.c文件是在Kernel文件夹下的,使用容器,需要用到容器接口,就如我们拿finish举过例子。例如,我们想找容器中的thread对象,我们应该怎么用呢?

rt_object_get_information()函数

              用rt_object_get_information()函数

/**
 * This function will return the specified type of object information.
 *
 * @param type the type of object
 * @return the object type information or RT_NULL
 */
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;
}

  for循环遍历,因为使用宏定义会屏蔽掉一下不使用的功能,所以,用for循环遍历,而不是用switch语句。

rt_object_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_object_information *information;
#ifdef RT_USING_MODULE
    struct rt_dlmodule *module = dlmodule_self();
#endif

    /* get object information */
    information = rt_object_get_information(type);
    RT_ASSERT(information != RT_NULL);

    /* initialize object's parameters */

    /* set object type to static */
    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));

    /* 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);
}

rt_object_init()函数还记得出现在哪里吗?
出现在rt_thread_init函数里的

rt_err_t rt_thread_init(struct rt_thread *thread,
						const char *name,
						void (*entry)(void *parameter),
						void *parameter,
						void *stack_start,
						rt_uint32_t stack_size)
{
	rt_object_init((rt_object_t)thread,RT_Object_Class_Thread,name);
	rt_list_init(&(thread->tlist);
}
  • 第一次使用CSDN的MakeDown编辑器来编辑文档,讲道理,还是有些生疏的。
  • RT-Thread讲道理对我来说,还是相当复杂的东西,限于自身能力的原因,在理解方面还是有些不太能Get到源码的点
  • 讲道理,写到这里已经是包含了线程的定义,优先级的实现,简单的不涉及优先级的调度以及对象容器的实现
对象 对象容器 线程 优先级列表 rt_object_init() rt_list_init() rt_object_init() rt_scheduler() rt_object_get_information() 对象 对象容器 线程 优先级列表

1.每个线程都会被挂在优先级列表上,优先级列表是为了解决多任务调度优先处理紧急任务的作用
2.每个线程都会被挂在对象容器上,对象容器是为了便于管理线程的运行状态,可以用finish输出对象的信息
3.这个表肯定是不完善的,其实,还有更多的信息。对于一个semaphore来说,它本身只是一个拥有rt_ipc_object对象和一个value的信息量值罢了,它本身只是一个对象,所有对它的操作,都将在thread中运行。所以对于一个包含了semaphore操作的线程来说,线程需要执行一次rt_object_init()来将线程挂在到对象容器中,semaphore也将执行rt_object_init()来将自己插入到对象容器中 对象都包括哪些 RT-Thread中,所有的数据结构都称之为对象

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 2018年中级网络工程师考试,是网络工程师考试中的一个重要等级。这个等级是考察考生对网络工程技术的掌握程度和实践能力的综合考试。网络工程师是指在计算机网络领域具有一定专业技术知识和实际工作经验的人员,负责网络设计、搭建、维护和管理等工作。 2018年中级网络工程师考试分为两个科目,分别是理论知识和实践操作。理论知识包括网络架构、网络设备、网络协议等方面的知识,要求考生对这些知识点有深入的理解和掌握。实践操作要求考生对网络搭建、调试、故障排除等方面的实际操作技能进行考核。 考生需要通过准备网络工程师的相关课程和考试资料,系统地学习和掌握网络工程师的理论知识和实践操作技能。在备考过程中,可以通过参加培训班、做题练习和实践操作等方式来提高自己的技能水平。 网络工程师是一个不断发展和更新的职业,随着科技的不断进步和应用的广泛推广,网络工程师的需求也越来越高。2018年中级网络工程师考试是机会和挑战并存的一次考试,只有通过不断学习和实践,不断提高自己的专业能力,才能在这个竞争激烈的行业中立于不败之地,成为一名优秀的网络工程师。 ### 回答2: 2018年中级网络工程师是even_yy。even_yy拥有一定的网络工程知识和技能,在网络设备的安装、配置和维护方面具有扎实的实践经验。他对于网络拓扑结构、协议以及网络安全有着深入的理解,并能够运用这些知识和技能解决各种网络故障和问题。 在工作中,even_yy能够根据需求和情况设计和实施适当的网络解决方案,保证网络的稳定性和安全性。他有良好的沟通能力和团队合作意识,能够与团队成员和其他部门的人员有效地合作,协调解决网络问题。 even_yy还具备一定的故障诊断和故障排除能力,能够快速定位网络故障的根本原因,并采取相应的措施进行修复。他熟悉各种网络设备的配置和管理,能够对设备进行监控和管理,及时发现并解决潜在问题,确保网络的正常运行。 此外,even_yy对于网络技术的学习和更新持有积极的态度,时刻关注行业的最新动态,通过参加培训和认证考试来提升自己的专业水平。他具备快速学习新知识和适应新环境的能力,能够随着技术的发展不断提升自己的能力和价值。 总的来说,even_yy是一名具备扎实网络工程知识和技能的中级网络工程师,他具有解决各类网络问题的能力,并具备团队合作和学习能力,是一个有价值的网络工程师。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值