首页 理论教育 操作系统实现之路:线程消息队列

操作系统实现之路:线程消息队列

时间:2023-10-21 理论教育 版权反馈
【摘要】:图4-7 线程消息队列的添加操作线程本身可以调用GetMessage函数,从自己的消息队列中获取消息。若当前消息队列为空,则GetMessage函数阻塞,直到有其他线程向本线程的消息队列中发送消息。图4-8 线程消息队列的删除操作队列当前的状态(空或满)可以通过判断ucCurrentMsgNum的大小获得。消息队列机制的应用十分广泛,也十分灵活,从理论上说,任何基于多线程通信的应用模型都可以使用消息队列来实现。

操作系统实现之路:线程消息队列

消息队列是一个由数组结构构成的循环队列,即核心线程对象(__KERNEL_THREAD_OBJECT)定义的KernelThreadMsg数组,为方便阅读,把核心线程对象定义中关于线程消息队列的部分代码列举如下:

978-7-111-41444-5-Chapter04-42.jpg

KernelThreadMsg数组是一个类型为__KERNEL_THREAD_MESSAGE结构的数组,根据目前的定义,该数组大小是32(在实际代码中,以宏定义MAX_KTHREAD_MSG_NUM替代硬编码的32)。ucAligment是为了实现数据对齐(32bit对齐),ucQueueHeader和ucQueueTail分别指向队列的头部和尾部,其中,ucQueueHeader指向队列的第一个非空元素(若队列非空的话),而ucQueueTail指向了消息队列中第一个空元素(若队列不满的话)。ucCurrentMsgNum则指出了当前队列中消息的个数,如图4-6所示。

978-7-111-41444-5-Chapter04-43.jpg

图4-6 线程的消息队列

系统中的核心线程可以通过SendMessage函数调用向队列中发送消息,如果队列不满,则消息被存储在ucQueueTail所指向的位置,同时ucQueueTail后移一个元素(指向下一个非空位置),ucCurrentMsgNum增加1,如图4-7所示。

978-7-111-41444-5-Chapter04-44.jpg

图4-7 线程消息队列的添加操作

线程本身可以调用GetMessage函数,从自己的消息队列中获取消息。若当前消息队列为空,则GetMessage函数阻塞(通过等待一个EVENT核心对象),直到有其他线程向本线程的消息队列中发送消息。若消息队列非空,则GetMessage函数取走ucQueueHeader所指位置的消息,然后ucQueueHeader向后移动一个位置,ucCurrentMsgNum减1,如图4-8所示。

978-7-111-41444-5-Chapter04-45.jpg

图4-8 线程消息队列的删除操作

队列当前的状态(空或满)可以通过判断ucCurrentMsgNum的大小获得。(www.xing528.com)

lpMsgEvent是一个__EVENT内核对象,该对象用来完成消息操作的同步。在当前Hello China的实现中,GetMessage函数是按照同步操作实现的。即若队列中有消息,则该函数立即返回,并把队列中的消息返回给用户程序;若队列中没有消息,则该函数阻塞,直到有消息到达。阻塞操作就是通过等待该事件对象实现的。下面是GetMessage函数的相关代码。

978-7-111-41444-5-Chapter04-46.jpg

在上述实现中,GetMessage函数首先判断线程的消息队列是否为空,若为空,则调用lpMsgEvent对象的WaitForThisObject函数等待lpMsgEvent对象。

而lpMsgEvent对象是被SendMessage函数唤醒的,SendMessage函数的相关实现代码如下:

978-7-111-41444-5-Chapter04-47.jpg

978-7-111-41444-5-Chapter04-48.jpg

在上述实现中,每向线程队列发送一个消息,就会调用SetEvent函数设置事件对象的状态,这样若当前线程因为调用GetMessage函数阻塞,此时就会被唤醒。

对于线程的消息队列,最后需要解释的就是__KERNEL_THREAD_MESSAGE结构本身了,顾名思义,该结构用来装载具体的消息,定义如下:

978-7-111-41444-5-Chapter04-49.jpg

wCommand是一个命令字,指出具体的消息类型,比如键盘按下、鼠标按下等,也可以由用户自己定义。wParam和dwParam是两个与wCommand关联的参数,比如,与“键盘按下”这样一个消息相关联,可以是具体被按下的键的ASCII码(可以通过wParam设置)。

消息队列机制的应用十分广泛,也十分灵活,从理论上说,任何基于多线程通信的应用模型都可以使用消息队列来实现。

免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。

我要反馈