Welcome 微信登录
编程资源 图片资源库 蚂蚁家优选 PDF转换器

首页 / 操作系统 / Linux / Linux下模拟一个简易的消息机制

消息机制是WIN32的核心,本质就是一个消息结构的链表。声明#define MSG_ERROR -1#define MSG_SUCCEED 0 #define MSG_TRUE 1#define MSG_FALSE 0 #define PM_NOREMOVE 0x00#define PM_REMOVE 0x01 typedef unsigned longWPARAM; typedef unsigned longLPARAM; typedef unsigned intUINT; typedef intMSG_BOOL;//这个返回值很二 不要喷我... typedef struct{UINTmessage;//消息类型 UINTidThread;//线程ID WPARAMwParam;LPARAMlParam;}MSG;typedef MSG* LPMSG;typedef struct NODE{MSG data;struct NODE* next;}MSG_NODE;void SetupMessage();//启动消息队列 void TerminalMessage();//终止消息队列MSG_BOOL PeekMessage( LPMSG lpMsg,UINT hWnd,UINT wMsgFilterMin,UINT wMsgFilterMax,UINT wRemoveMsg); MSG_BOOL PostThreadMessage( UINT idThread,UINT msg,WPARAM wParam,LPARAM lParam);实现#include "msg.h" #include <stdio.h>#include <stdlib.h>#include <string.h>#include <assert.h>#include <pthread.h> static MSG_NODE * g_message_queue = NULL;static MSG_NODE* msg_create(){MSG_NODE* pHead = calloc(sizeof(MSG_NODE),1);return pHead;}static void msg_destroy(MSG_NODE* pHead){MSG_NODE* pNode = NULL;if(pHead){pNode = pHead->next;while(pNode){pHead->next = pNode->next;printf("Free Node:%p ",pNode);free(pNode);pNode = pHead->next;}free(pHead);printf("Free Head Node:%p ",pHead);}}//定位到消息列表尾部static MSG_NODE* msg_tail(MSG_NODE* pHead){MSG_NODE* pTail = NULL; if(!pHead) return NULL;pTail = pHead;while(pTail->next) pTail = pTail->next;return pTail;}//尾部插入一个消息结点static int msg_push_back(MSG_NODE* pHead, MSG_NODE* pNode){MSG_NODE* pTail = NULL; if( !pHead || !pNode) return MSG_ERROR; pTail = msg_tail(pHead);if(pTail){pTail->next = pNode;pNode->next = NULL;return MSG_SUCCEED;}return MSG_ERROR;}//启动void SetupMessage(){if(!g_message_queue){g_message_queue = msg_create();assert(g_message_queue);}}//终止void TerminalMessage(){msg_destroy(g_message_queue);g_message_queue = NULL;}  MSG_BOOL PostThreadMessage(UINT idThread,UINT msg, WPARAM wParam, LPARAM lParam){MSG_NODE* pNode = NULL; if( !g_message_queue && (msg < 0) ) return MSG_FALSE; pNode = calloc(sizeof(MSG_NODE),1);if (pNode){pNode->data.message = msg;pNode->data.idThread = (!idThread)?pthread_self():idThread;//如果ID是0 默认为当前线程 pNode->data.wParam = wParam;pNode->data.lParam = lParam;pNode->next = NULL;return (msg_push_back(g_message_queue,pNode) == MSG_SUCCEED)?MSG_TRUE:MSG_FALSE;}return MSG_FALSE;}//第二个参数完成为了函数"像" Win32 API 没有用处,LINUX没有窗口句柄这一说 MSG_BOOL PeekMessage(LPMSG lpMsg,UINT HWND,UINT wMsgFilterMin,UINT wMsgFilterMax,UINT wRemoveMsg){MSG_NODE* pNode = NULL;MSG_NODE* pPreNode = NULL;//保存前一个结点if( !g_message_queue && lpMsg) return MSG_FALSE; pPreNode = g_message_queue;pNode = g_message_queue->next; /**不要喷我 用这么多goto啊 只是为了 不要写一堆重复的代码*/while(pNode){if(pNode->data.idThread != (UINT)pthread_self() ){goto NEXT;} if(wMsgFilterMin|wMsgFilterMax){if( pNode->data.message >= wMsgFilterMin &&pNode->data.message <= wMsgFilterMax ){goto GET_MSG;}}else{goto GET_MSG;} NEXT:pPreNode = pNode;pNode = pNode->next;continue; GET_MSG:memcpy(lpMsg,&pNode->data,sizeof(MSG) );if(wRemoveMsg == PM_REMOVE)//删除消息链表结点 {pPreNode->next = pNode->next;//前驱结点关联后继结点 防止链表截断 free(pNode);//释放当前消息链表结点 }return MSG_TRUE;}return MSG_TRUE;}测试用例
#include <stdio.h>#include <string.h>#include "msg.h"int main(int argc,char** argv){int i=0;MSG msg; SetupMessage(); for(i=0;i<10;i++){PostThreadMessage(0,1000+i, 100+i, 200+i);} while(1){PeekMessage(&msg,0,0,0,PM_REMOVE);printf("ID:%u,WPARAM:%lu,LPARAM:%lu ",msg.message,msg.wParam,msg.lParam);if(!msg.message)break;memset(&msg,0,sizeof(MSG));sleep(2);}TerminalMessage();return 0;}测试用例只是做了一些简单基础的测试,并不完善。除了线程相关的系统调用,全部采用标准库实现。本文永久更新链接地址:http://www.linuxidc.com/Linux/2014-08/105546.htm