Linux下模拟一个简易的消息机制

声明

#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 long 	WPARAM;
typedef unsigned long 	LPARAM;
typedef unsigned int	UINT;
typedef int				MSG_BOOL;//这个返回值很二 不要喷我...

typedef struct
{
	UINT 	message;//消息类型
	UINT 	idThread;//线程ID
	WPARAM	wParam;
	LPARAM	lParam;
}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\n",pNode);
			free(pNode);
			pNode = pHead->next;
		}
		free(pHead);
		printf("Free Head Node:%p\n",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\n",msg.message,msg.wParam,msg.lParam);
		if(!msg.message)break;
		memset(&msg,0,sizeof(MSG));
		sleep(2);
	}
	TerminalMessage();
	return 0;
}

测试用例只是做了一些简单基础的测试,并不完善。

除了线程相关的系统调用,全部采用标准库实现。

Linux下模拟一个简易的消息机制

时间: 2024-08-07 21:16:29

Linux下模拟一个简易的消息机制的相关文章

linux下模拟一个木马程序运行过程

预备知识: 将一个程序放入到后台,悄悄的执行 ./xxx.sh & 进程: 用户进程:由用户来管理 系统进程:由系统内核自行管理 系统中的每个进程,都有一个位置的ID,这就是pid,而且每次启动进程以后,PID都不相同 进程相关的命令 jobs 作用:查看当前运行在后台的进程有哪些 信息 第一列:进程编号 第二列:进程状态 第三列:进程是如何发起的 fg   进程编号    把进程从后台调到前台执行 kill %进程编号  杀死进程 ps aux   打印系统所有进程 num=`ps aux |

Linux下模拟多线程的并发并发shell脚本

分享一个在Linux下模拟多线程的并发脚本,使用这个脚本可以同时批量在定义数量的服务器上执行相关命令,比起普通for/while循环只能顺序一条一条执行的效率高非常多,在管理大批服务器时非常的实用.     以下脚本功能是通过scp(也可选rsync)向上千台服务器传更新包,脚本运行后同时在后台有50个scp进程向服务器传包.#!/bin/baship=`cat iplist.txt|grep -v "#"|awk '{print $1}'`   #过滤服务器IPdir='/usr/l

如何在Linux下拷贝一个目录呢

cp -af newadmin/movie/.   uploadfile/mallvideo/ 如何在Linux下拷贝一个目录呢?这好像是再简单不过的问题了. 比如要把/home/usera拷贝到/mnt/temp,首先想到的就是 cp -R /home/usera/* /mnt/temp 但是这样有一个问题,/home/usera下的隐藏文件都不会被拷贝,子目录下的隐藏文件倒是会的. 那如何才是正确的方法呢?有人说用-a选项,有人说用find加管道. 其实没这么复杂,Google了之后,学了一

Lua 下实现一个简单的消息队列

Lua 下实现一个简单的消息队列,如下简单的几条代码就可以了. local q1 = {} local q2 = {} -- 产生消息只需要 table.insert(q1, msg) -- 分发消息需要两层循环, 可以处理 dispatch 过程中产生的新消息 while q1[1] do q1,q2 = q2,q1 for i=1,#q2 do dispatch(q2[i]) q2[i] = nil end end

【转载】在Linux下,一个文件也有三种时间,分别是:访问时间、修改时间、状态改动时间

在windows下,一个文件有:创建时间.修改时间.访问时间.而在Linux下,一个文件也有三种时间,分别是:访问时间.修改时间.状态改动时间. 两者有此不同,在Linux下没有创建时间的概念,也就是不能知道文件的建立时间,但如果文件建立后就没有修改过,修改时间=建立时间;如果文件建立后,状态就没有改动过,那么状态改动时间=建立时间;如果文件建立后,没有被读取过,那么访问时间=建立时间,因为不好判断文件是否被改过.读过.其状态是否变过,所以判断文件的建立时间基本上能为不可能. 如何查一个文件的三

linux 下查看一个进程运行路径

在linux下查看进程大家都会想到用 ps -ef|grep XXX 可是看到的不是全路径,怎么看全路径呢? 每个进程启动之后在 /proc下面有一个于pid对应的路径 例如:ps -ef|grep python 显示:oracle    4431  4366  0 18:56 pts/2    00:00:00 python Server.py 4431就是进程号 到/proc/4431下,ls -l 会看到(需要root权限): 总用量 0 -r--r--r--    1 oracle  

Linux下TCP延迟确认(Delayed Ack)机制导致的时延问题分析

版权声明:本文由潘安群原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/105 来源:腾云阁 https://www.qcloud.com/community 案例一:同事随手写个压力测试程序,其实现逻辑为:每秒钟先连续发N个132字节的包,然后连续收N个由后台服务回显回来的132字节包.其代码简化如下: char sndBuf[132]; char rcvBuf[132]; while (1) { for (int i

linux下,一个运行中的程序,究竟占用了多少内存

1. 在linux下,查看一个运行中的程序, 占用了多少内存, 一般的命令有 (1). ps aux: 其中  VSZ(或VSS)列 表示,程序占用了多少虚拟内存. RSS列 表示, 程序占用了多少物理内存. 虚拟内存可以不用考虑,它并不占用实际物理内存. (2). top 命令也可以 其中  VIRT(或VSS)列  表示,程序占用了多少虚拟内存. 同 ps aux 中的 VSZ列 RES列 表示, 程序占用了多少物理内存.同 ps aux 中的RSS列 2.在linux下, 查看当前系统占用

linux 下模拟延时与丢包 tc qdisc

TC qdisc linux下的流量控制 修改ping测试的延时 增加规则: # tc qdisc add dev eth0 root 删除规则: # tc qdisc add dev eth0 root 修改规则: # tc qdisc change dev eth0 root 查看规则: # tc qdisc list Or # tc qdisc show 使用从eth0接口ping的延时为1000ms  上下波动为10ms tc qdisc add dev eth0 root netem