• 嵌入式实时操作系统的设计与开发(消息)


    消息

    从概念上讲,消息机制和邮箱机制很类似,区别在于邮箱一般只能容纳一条消息,而消息则会包含一系列的消息
    在这里插入图片描述
    系统定义了一个全局变量g_msgctr_header,通过它可以查找到任一已创建的消息容器。
    每一个消息容器都可以根据其参数性质(1VS1:1对1的消息通信、1VSn:1对多的消息通信、nVSn:多对多的消息通信、nVS1等)来实现不同的通信方式。

    这里的消息容器,只是一个线程间的通信结构acoral_msgctr_t,是消息的存储容器,一个消息容器可以通过它的消息链指针成员,挂载多条消息结构。
    而消息结构是消息的容器,一个消息结构包含一条消息。

    aCoral并没有采用数组之间存储消息指针的经典实现形式,而是在消息上又包装了一层结构,这样的实现是为了功能上的扩展,只要稍作改进,就可以实现消息功能的进一步增加,如消息最大生存时间,一次唤醒多个等待线程等功能。

    //消息容器
    typedef struct
    {
    	acoral_res_t res; //消息容器也是资源
    	char *name;
    	acoral_list_t msgctr_list;//全局消息容器的挂载钩子
    	unsigned int count; //消息数量
    	unsigned int wait_thread_num; //等待线程数
    	acoral_list_t waiting; //等待线程指针链
    	acoral_list_t msglist;//消息指针链,用于挂载消息
    }acoral_msgctr_t;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    //消息
    typedef struct
    {
    	acoral_res_t res;
    	acoral_list_t msglist; //挂载钩子成员,用于将消息结构挂载到消息容器上
    	unsigned int id; //消息标识,用于区分一个消息容器不同消息结构类型的成员,通过它可以实现1VSn的结构。
    	unsigned int count;//消息被接收次数,每接受一次减一,直到0为止。通过它可以实现一次发送,多次接收的功能。
    	unsigned int ttl;//消息最大生存周期,当一个消息生存周期到时,将自动删除,不可以再被接收。
    	void *data; //消息指针
    }acoral_msg_t;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    如何创建消息容器,以供线程间传递数据使用。

    acoral_msgctr_t *acoral_msgctr_create()
    {
    	acoral_msgctr_t *msgctr;
    	msgctr = acoral_alloc_msgctr();//申请一片内存空间,分配的方式和过程与线程TCB的分配类似,即从内存资源池中获取一个资源对象供消息容器acoral_msgctr_t使:return (acoral_msgctr_t *)acoral_get_res(&acoral_msgctr_pool_ctrl);
    	if(msgctr == NULL)
    		return NULL;
    	msgctr->name = NULL;
    	msgctr->count = 0;
    	msgctr->wait_thread_num = 0;
    	
    	acoral_init_list(&msgctr->msgctr_list);
    	acoral_init_list(&msgctr->msglist);
    	acoral_init_list(&msgctr->waiting);
    
    	acoral_list_add2_tail(&msgctr->msgctr_list, &(g_msgctr_header));
    	return msgctr;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    创建消息,前面提到,消息容器并不直接包含消息,在消息容器之下,还有一层消息结构因而消息的创建,即是先创建消息结构,再将消息挂到消息结构的过程。

    acoral_msg_t *acoral_msg_create(unsigned int count,unsigned int id, unsigned int nTtl, void *data)
    {
    	acoral_msg_t *msg;
    	msg = acoral_alloc_msg();
    	if(msg == NULL)
    		return NULL;
    	msg->id = id;
    	msg->count = count;
    	msg->ttl = nTtl;
    	msg->data = data;
    	acoral_init_list(&msg->msglist);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    一个消息的创建接口需要五个参数:消息被接收次数、错误码、消息ID、生存周期和消息指针(指向被发送的消息)。

    其中前三个参数都是为了扩展而引入的,aCoral只提供了接口和基本实现,但并未在消息传递具体过程中使用,如果需要进行扩展,只需要简单更改源代码即可,用于功能的扩充。

    发送消息:aCoral消息发送是需要先前创建的消息容器队列和消息队列。消息发送时,首先将包含消息的消息结构挂到消息容器的消息链上,然后判断是否有等待的线程,如果有的话,则唤醒最高优先级的线程。

    unsigned int acoral_msg_send(acoral_msgctr_t *msgctr, acoral_msg_t *msg)
    {
    	acoral_enter_critical();
    	if (NULL == msgctr)
    	{
    		acoral_exit_critical();
    		return MST_ERR_NULL;
    	}
    
    	if (NULL == msg)
    	{
    		acoral_exit_critical();
    		return MSG_ERR_NULL;
    	}
    	//消息数限制
    	if(ACORAL_MESSAGE_MAX_COUNT <= msgctr->count)
    	{
    		acoral_exit_critical();
    		return MSG_ERR_COUNT;
    	}
    	//增加消息
    	msgctr->count++;
    	msg->ttl += acoral_get_ticks();
    	acoral_list_add2_tail(&msg->msglist, &msgctr->msglist);
    
    	//唤醒等待
    	if(msgctr->wait_thread_num > 0)
    	{
    		wake_up_thread(&msgctr->wiating);
    		msgctr->wait_thread_num--;
    	}
    	acoral_exit_critical();
    	acoral_sched();
    	return MSGCTR_SUCCED;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
  • 相关阅读:
    JAVA计算机毕业设计医疗健康管理平台会员管理子系统Mybatis+源码+数据库+lw文档+系统+调试部署
    【信创】麒麟v10(arm)-mysql8-mongo-redis-oceanbase
    [附源码]java毕业设计哈金院快递驿站管理信息系统
    08-JS对象、原型及原型链
    【JVM技术专题】 深入分析字节码指令重排序技术「原理篇」
    3D模型如何添加表面贴图?
    代码随想录Day59 | 647. 回文子串 | 516. 最长回文子序列
    手机上免费更改地址大全
    Ubantu安装教程(其实和之前CentOS差不多)
    Linux搭建redis调试环境
  • 原文地址:https://blog.csdn.net/Caramel_biscuit/article/details/134005029