Raw-OS源代码分析之消息系统-Queue_Buffer

分析的内核版本号截止到2014-04-15,基于1.05正式版。blogs会及时跟进最新版本号的内核开发进度,若源代码凝视出现”???”字样,则是未深究理解部分。

Raw-OS官方站点:http://www.raw-os.org/

Raw-OS托管地址:https://github.com/jorya/raw-os/

有了之前的queue和queue_size的解读之后。这个queue_buffer就很之简单了~对于queue是转发消息的指针,queue_size则是转发消息指针和消息大小。那么queue_buffer不在转存消息的指针,而是将消息copy一份,转发消息内容和消息大小。

这个定义一个queue_buffer消息的概念~

一个queue_buffer消息包含消息的大小,消息详细数据内容,然后依照上图的结构进行排列~那么在queue_buffer中,详细消息是封装成以上的结构进行转发的~

那么在queue_buffer建立的内部数据存储仓库,queue_buffer的消息按这样排列的

当中,head指针指向queue_buffer消息存在的開始位置。tail指针指向queue_buffer消息存在的末尾位置,剩余的没转存消息的位置称为空暇消息

还有注意一点的就是。queue_buffer的queue_buffer消息一定要按4字节对齐的形式存储在queue_buffer的存储仓中,原因的话要详细看代码才干说明确

Queue_buffer消息的转存过程和queue和queue_size一样,仅仅是内核多了复制详细数据这一部的操作,至于在转存仓库的组织形式,都是按各自的消息结构体来组织。queue消息是指向消息的void指针,queue_size就是以消息指针和消息大小组成的queue_size结构体,那么到这里queue_buffer就是以消息长度+消息实际内容的形式。

代码仅仅说明queue_buffer建立。发送queue_buffer消息到queue_buffer的部分

1.queue_buffer的创建

RAW_U16 raw_queue_buffer_create(RAW_QUEUE_BUFFER *q_b, RAW_U8 *p_name, RAW_VOID *msg_buffer, MSG_SIZE_TYPE buffer_size, MSG_SIZE_TYPE max_msg_size)
{
	MSG_SIZE_TYPE bufsz;
	RAW_U8        queue_buffer_align_mask;
	/* 检查创建消息buffer的边界条件 */
	#if (RAW_QUEUE_BUFFER_FUNCTION_CHECK > 0)
	if (q_b == 0) {
		return RAW_NULL_OBJECT;
	}

	if (msg_buffer == 0) {
		return RAW_NULL_POINTER;
	}
	#endif
	/* 消息buffer的大小必须满足4字节的整数倍 */
	bufsz = ROUND_BUFFER_SIZE(buffer_size);
	/* 消息buffer大小为0时,错误返回 */
	if (bufsz == 0) {
		return RAW_QUEUE_BUFFER_SIZE_0;
	}
	/* 消息buffer大小不满足4字节对齐时,错误返回 */
	if (bufsz != buffer_size) {
		return RAW_QUEUE_BUFFER_INVALID_SIZE;
	}

	queue_buffer_align_mask = HEADERSZ - 1u;
	/* 消息buffer的内部存储消息的仓库的地址相同也要满足4字节的整数倍对齐 */
	if (((RAW_U32)msg_buffer & queue_buffer_align_mask)){
		return RAW_INVALID_ALIGN;
	}

	/* 初始化消息buffer的堵塞链表头 */
	list_init(&q_b->common_block_obj.block_list);

	q_b->bufsz = bufsz;
	q_b->frbufsz = bufsz;
	q_b->buffer = msg_buffer;
	q_b->maxmsz = max_msg_size;
	q_b->head = 0;
	q_b->tail = 0;

	q_b->common_block_obj.name = p_name;
	q_b->common_block_obj.block_way = RAW_BLOCKED_WAY_PRIO;
	q_b->common_block_obj.object_type = RAW_QUEUE_BUFFER_OBJ_TYPE;

	TRACE_QUEUE_BUFFER_CREATE(raw_task_active, q_b);

	return RAW_SUCCESS;

}

2.发送queue_buffer消息

RAW_U16 raw_queue_buffer_end_post(RAW_QUEUE_BUFFER *q_b, RAW_VOID *p_void, MSG_SIZE_TYPE msg_size)
{
	/* 发送queue buffer消息时的边界条件检查 */
	#if (RAW_QUEUE_BUFFER_FUNCTION_CHECK > 0)
	if (q_b == 0) {
		return RAW_NULL_OBJECT;
	}

	if (p_void == 0) {
		return RAW_NULL_POINTER;
	}
	/* 发送queue buffer消息长度不能超过创建queue_buffer定义的最大消息长度 */
	if (msg_size > q_b->maxmsz) {
		return RAW_EXCEED_QUEUE_BUFFER_MSG_SIZE;
	}
	#endif

	/* 开启0中断特性后。不能在中断ISR中发送queue_buffer,而queue和queue_size能够,想想为什么??? */
	#if (CONFIG_RAW_ZERO_INTERRUPT > 0)
	if (raw_int_nesting) {
		return RAW_NOT_CALLED_BY_ISR;
	}
	#endif

	return queue_buffer_post(q_b, p_void, msg_size, SEND_TO_END);
}

存储queue_buffer的核心代码

RAW_U16 queue_buffer_post(RAW_QUEUE_BUFFER *q_b, RAW_VOID *p_void, MSG_SIZE_TYPE msg_size, RAW_U8 opt_send_method)
{
	LIST *block_list_head;
	RAW_TASK_OBJ *task_ptr;

 	RAW_SR_ALLOC();

	RAW_CRITICAL_ENTER();

	if (q_b->common_block_obj.object_type != RAW_QUEUE_BUFFER_OBJ_TYPE) {

		RAW_CRITICAL_EXIT();
		return RAW_ERROR_OBJECT_TYPE;
	}

	block_list_head = &q_b->common_block_obj.block_list;

	if (!is_queue_buffer_free(q_b, msg_size)) {

		RAW_CRITICAL_EXIT();

		TRACE_QUEUE_BUFFER_MAX(raw_task_active, q_b, p_void, msg_size, opt_send_method);

		return RAW_QUEUE_BUFFER_FULL;
	}

	/* 当queue_buffer内部存储仓未满时,就会将消息转存到存储仓里面。并且内部仅仅实现发送存储仓末尾的操作 */
	if (is_list_empty(block_list_head)) {

		if (opt_send_method == SEND_TO_END)  {
			msg_to_end_buffer(q_b, p_void, msg_size);
		}

		else {
			/* 没有定义有除发送到存储仓末尾外的操作 */
		}

		RAW_CRITICAL_EXIT();

		TRACE_QUEUE_BUFFER_POST(raw_task_active, q_b, p_void, msg_size, opt_send_method);

		return RAW_SUCCESS;
	}
	/*
	 * 假设有任务堵塞在queue_buffer上等待消息,个人觉得以下这些操作是为了加快消息传递,
	 * 不由queue_buffer的内部存储仓转存数据内容。少了一个二次copy的过程
	 *
	 * 找到queue_buffer的堵塞链表的最高优先级任务,然后直接将消息内容和大小copy到任务控制块中,然后唤醒该任务
	 */
	task_ptr = list_entry(block_list_head->next, RAW_TASK_OBJ, task_list);

	raw_memcpy(task_ptr->msg, p_void, msg_size);
	task_ptr->qb_msg_size = msg_size;

	raw_wake_object(task_ptr);

	RAW_CRITICAL_EXIT();

	TRACE_QUEUE_BUFFER_WAKE_TASK(raw_task_active, list_entry(block_list_head->next, RAW_TASK_OBJ, task_list), p_void, msg_size, opt_send_method);

	raw_sched();
	return RAW_SUCCESS;
}
时间: 2024-09-30 19:08:26

Raw-OS源代码分析之消息系统-Queue_Buffer的相关文章

Raw-OS源代码分析之消息系统-Queue_Size

分析的内核版本号截止到2014-04-15.基于1.05正式版.blogs会及时跟进最新版本号的内核开发进度,若源代码凝视出现"???"字样,则是未深究理解部分. Raw-OS官方站点:http://www.raw-os.org/ Raw-OS托管地址:https://github.com/jorya/raw-os/ 有了前一讲queue的基础后,这次来说说queue_size这个模块,前一讲的queue通信,知道queue在通信时,为了加快数据的传递速度.是不直接发送数据的详细内容.

Memcached源代码分析 - Memcached源代码分析之消息回应(3)

文章列表: <Memcached源代码分析 - Memcached源代码分析之基于Libevent的网络模型(1)> <Memcached源代码分析 - Memcached源代码分析之命令解析(2)> <Memcached源代码分析 - Memcached源代码分析之消息回应(3)  > <Memcached源代码分析 - Memcached源代码分析之HashTable(4) > <Memcached源代码分析 - Memcached源代码分析之增删

[Android源代码分析]Android消息机制,Handler,Message,Looper,MessageQueue

最近准备把Android源码大致过一遍,不敢私藏,写出来分享给大家,顺便记录一下自己的学习感悟.里面一定有一些错误的地方,希望广大看客理解理解. 网上也有不少分析文章,这里我尽量分析的更加细致详尽.不留死角. 一.核心循环体:Looper.loop(); 我们知道,在线程run()中Looper.prepare();Looper.looper().之后这个线程就是一个HandlerThread了.我们可以通过Handler在另外一个线程中(自己也可以)向这个线程发送消息,在这个线程中处理消息.

1.4. chromium源代码分析 - chromiumframe - 消息系列

Message framework 是对消息循环的封装和扩展,Chromium在消息循环中增加处理内部任务的工作.将内部工作处理寄生在Windows的消息循环中,会有一个问题,就是没有Windows自身消息,而有Chromium内部工作,此时内部动作就无法及时处理.Chromium这里定义了一个自定义消息kMsgHaveWork,用来在Chromium内部有工作的时候,驱动Windows的消息一直会运行. 从代码级别来说,Chromium内部工作队列被塞入工作时Post一条kMsgHaveWor

android 消息系统Handler、MessageQueue、Looper源代码学习

android消息系统 总体框架如图所看到的 在安卓的消息系统中,每一个线程有一个Looper,Looper中有一个MessageQueue,Handler向这个队列中投递Message,Looper循环拿出Message再交由Handler处理.总体是一个生产者消费者模式,这四部分也就构成了android的消息系统. 先来看一个最简单的样例 //这段代码在某个Activity的onCreate中 Handler handler = new Handler(Looper.getMainLoope

Android系统进程Zygote启动过程的源代码分析

原文地址:http://blog.csdn.net/luoshengyang/article/details/6747696 Android应用程序框架层创建的应用程序进程具有两个特点,一是进程的入口函数是ActivityThread.main,二是进程天然支持Binder进程间通信机制:这两个特点都是在进程的初始化过程中实现的,本文将详细分析Android应用程序进程创建过程中是如何实现这两个特点的. Android应用程序框架层创建的应用程序进程的入口函数是ActivityThread.ma

Android应用程序进程启动过程的源代码分析

文章转载至CSDN社区罗升阳的安卓之旅,原文地址: http://blog.csdn.net/luoshengyang/article/details/6747696 Android 应用程序框架层创建的应用程序进程具有两个特点,一是进程的入口函数是ActivityThread.main,二是进程天然支持Binder进程间通信 机制:这两个特点都是在进程的初始化过程中实现的,本文将详细分析Android应用程序进程创建过程中是如何实现这两个特点的. Android应用程序框架层创建的应用程序进程

android 消息系统Handler、MessageQueue、Looper源码学习

android消息系统 整体框架如图所示 在安卓的消息系统中,每个线程有一个Looper,Looper中有一个MessageQueue,Handler向这个队列中投递Message,Looper循环拿出Message再交由Handler处理.整体是一个生产者消费者模式,这四部分也就构成了android的消息系统. 先来看一个最简单的例子 //这段代码在某个Activity的onCreate中 Handler handler = new Handler(Looper.getMainLooper()

Android系统进程间通信Binder机制在应用程序框架层的Java接口源代码分析

文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6642463 在前面几篇文章中,我们详细介绍了Android系统进程间通信机制Binder的原理,并且深入分析了系统提供的Binder运行库和驱动程序的 源代码.细心的读者会发现,这几篇文章分析的Binder接口都是基于C/C++语言来实现的,但是我们在编写应用程序都是基于Java语言的,那么,我 们如何使用Java语言来使用系统的Binder机