|
楼主 |
发表于 2006-6-17 19:19:39
|
显示全部楼层
-------------------------------------------------------------------
to:楼上
一口一个老师的……我要折寿的……看清楚帖子,交流二字写得多大的……
下一个章节会提到函数指针的,敬请期待。最近正在写事件驱动系统,不好意思,更新会慢一点。
先奉上一个事件驱动的主干雏形,大家有空的话劳烦慢慢看哈。
小弟又要献丑了……
#ifndef _USE_MSG_H_
#define _USE_MSG_H_
/***********************************************************
* 函数库说明:消息队列系统函数库 *
* 版本: v1.12 *
* 作者: 傻孩子 *
* 创建日期: 2006年5月24日 *
* -------------------------------------------------------- *
* [支持库] *
* 支持库名称:RD_MacroAndConst.h *
* 需要版本: v0.01 &abv *
* 函数库说明:系统常用宏定义库 *
* *
* 支持库名称:stdlib.h *
* 需要版本: 6.31A *
* 函数库说明:系统标准函数库 *
* *
* 支持库名称:RD_UseBITs.h *
* 需要版本: v1.00 &abv *
* 函数库说明:系统位段操作函数库 *
* -------------------------------------------------------- *
* [版本更新] *
* 修改: 傻孩子 *
* 修改日期: 2006年5月25日 *
* 版本: v1.10 *
* *
* 修改: 傻孩子 *
* 修改日期: 2006年5月30日 *
* 版本: v1.11 *
* *
* 修改: 傻孩子 *
* 修改日期: 2006年6月15日 *
* 版本: v1.12 *
* -------------------------------------------------------- *
* [版本历史] *
* v1.00 提供了消息循环队列的基本结构体声明和队列操 *
* 作函数。拥有一个基本的消息队列配送函数。 *
* 提供基本的消息创建、删除和复制函数。自动消 *
* 息垃圾收集。初步建立了一个消息函数地图。 *
* v1.10 建立的简单的进程处理构架。 *
* v1.11 增加了对消息类型鉴别的说明。增加了消息广播 *
* 功能。修改了消息的结构体,增加了消息的类型 *
* 鉴别字节。 *
* v1.12 将所有char型数据更新为unsigned char。 *
* 修改了进程处理函数的调度模式。 修正了指针 *
* 传递的错误。 *
* -------------------------------------------------------- *
* [使用说明] *
* 1、在系统初始化的时候调用函数MSGInit()来初始 *
* 化消息对系统;同时通过定义宏 *
* MSG_REGISTER_PROC_FUNCTION来说明静态进程函 *
* 数的消息处理函数和动作函数(使用函数指针)。 *
* 每增加一个静态进程,要更新一次进程计数器 *
* MSG_Proc_Counter,保证每一个进程都能被有效 *
* 的寻址。 *
* 2、通过宏 INSERT_EVENT_PROCCESS_LOOP_CODE() *
* 来指定默认的消息处理函数,并且通过插入该宏 *
* 到系统主循环中来保证整个消息处理系统的正常 *
* 运行。也可以使用宏 *
* INSERT_EVENT_PROCCESS_LOOP_DEFAULT_CODE来设 *
* 定默认的消息处理函数。 *
* 3、用户通过每一个进程的消息处理函数来处理消息 *
* 和动作函数之间的通讯,用户接收的消息无需自 *
* 行销毁,系统会统一的进行垃圾收集。如果用户 *
* 需要转发消息给别的进程,需要调用本库提供的 *
* 消息复制函数copyMSG来复制消息,并通过addMSG *
* 函数来添加消息到消息队列中。特别需要注意的 *
* 是,为了保证整个消息队列的实效性,在消息处 *
* 理函数中不要出现过长时间复杂度的代码。 *
* 4、系统为每一个消息都提供了一个消息类型的鉴别 *
* 标志,用户在发送消息的时候需要认真填写,这 *
* 些鉴别标志包括标志消息为错误信息;标志消息 *
* 为指令、数据;标志消息为广播等等。其中,广 *
* 播消息会自动发给所有的有效进程。错误的消息 *
* 类型将会导致不可预计的系统错误。 *
* 5、用户创建消息的时候,需要用专门的函数creatMSG*
* 并传递消息的正确描述。这些描述包括消息的发 *
* 送者函数指针,消息接收进程的消息处理函数指 *
* 针,消息的类型,消息的长度,和消息字节串。 *
* 6、用户可以通过宏MSG_QUEUE_SIZE来定义消息队列 *
* 的大小,值得注意的是,这个队列只是一个指针 *
* 队列,并不会占用过多的系统资源。 *
* 7、用户可以通过宏MSG_PROCESS_COUNT来定义最大的 *
* 进程PCB数量。这个数值直接影响系统允许的静态 *
* 进程的数量,并要占用一定的空间。这个数目的 *
* 最小值是1,因为默认有一个系统默认消息处理 *
* 进程。 *
* 8、用户需要MSG_REGISTER_MSG_FUNCTION宏来说明 *
* 系统进程的初始化函数,通过这个初始化函数告 *
* 诉消息系统,一共有多少静态进程,并且说明这 *
* 些静态进程的相关函数指针是什么。 *
***********************************************************/
# include <RD_MacroAndConst.h>
# include <stdlib.h>
# include <RD_UseBITs.h>
/********************
* 系 统 宏 定 义 *
********************/
/*------------------*
* 常 数 宏 定 义 *
*------------------*/
#ifndef MSG_QUEUE_SIZE
# define MSG_QUEUE_SIZE 50
#endif
#ifndef MSG_PROCESS_COUNT
# define MSG_PROCESS_COUNT 8
#endif
#ifndef MSG_REGISTER_MSG_FUNCTION
# define MSG_REGISTER_MSG_FUNCTION
#endif
# define NULLPROC NULLProc
/*------------------*
* 动 作 宏 定 义 *
*------------------*/
# define INSERT_EVENT_PROCCESS_LOOP_CODE(DEFAULT_FUNCTION_NAME) processMSG(DEFAULT_FUNCTION_NAME);
# define INSERT_EVENT_PROCCESS_LOOP_DEFAULT_CODE processMSG(SYS_DEFAULT);
# define MSG_FLAG(Flag) SET_BIT8_FORMAT(Flag)
# define MSG_FLAG_ERROR_BIT BIT0
# define MSG_FLAG_DATA_BIT BIT1
# define MSG_FLAG_CMD_BIT BIT2
# define MSG_FLAG_BROADCAST_BIT BIT3
# define MSG_FLAG_TEST_BIT BIT4
//# define MSG_FLAG_Reserved BIT5
//# define MSG_FLAG_Reserved BIT6
//# define MSG_FLAG_Reserved BIT7
# define MSG_FLAG_ERROR 0
# define MSG_FLAG_DATA 1
# define MSG_FLAG_CMD 2
# define MSG_FLAG_BROADCAST 3
# define MSG_FLAG_TEST 4
#ifndef MSG_REGISTER_PROC_FUNCTION
# define MSG_REGISTER_PROC_FUNCTION
#endif
# define SEND_MESSAGE(From,To,Flag,MsgLen,MSG) addMSG(creatMSG(From,To,Flag,MsgLen,MSG))
/********************
* 结构体宏定义 *
********************/
typedef struct Message
{
BOOL (*From)(volatile struct Message *MSG); //如果处理了信息,返回True,否则是False
BOOL (*To)(volatile struct Message *MSG);
unsigned char MsgLen;
unsigned char Flag; //消息类型鉴别字节
unsigned char *Msg; //消息指针
}MESSAGE;
typedef struct Process
{
BOOL (*ProcIO)(volatile MESSAGE *MSG);
void (*Proc)(void);
BOOL IfProcAlive;
}PROCESS;
/********************
* 全局变量声明区 *
********************/
volatile MESSAGE *MSG_Queue[MSG_QUEUE_SIZE];
volatile PROCESS ProcPCB[MSG_PROCESS_COUNT+1];
unsigned char MSG_Head = 0;
unsigned char MSG_Tail = 0;
unsigned char MSG_Counter = 0;
unsigned char MSG_Proc_Counter = 1; //进程计数器
/********************
* 函 数 声 明 区 *
********************/
BOOL addMSG(volatile MESSAGE *MSG);
BOOL getMSG(volatile MESSAGE **MSG);
void processMSG(BOOL (*Default)(volatile MESSAGE *MSG));
BOOL SYS_DEFAULT(volatile MESSAGE *MSG);
volatile MESSAGE *copyMSG(volatile MESSAGE *MSG);
void delMSG(volatile MESSAGE *MSG);
void MSGInit(void);
void NULLProc(void);
volatile MESSAGE *creatMSG(BOOL (*From)(volatile MESSAGE *MSG),BOOL (*To)(volatile MESSAGE *MSG),
unsigned char Flag,unsigned char MsgLen,unsigned char *Msg);
/***********************************************************
* 函数说明:空函数 *
***********************************************************/
void NULLProc(void)
{
}
/***********************************************************
* 函数说明:消息队列系统初始化函数 *
* -------------------------------------------------------- *
* [注意事项] *
* 1、ProcPCB[]是一个函数指针数组,里面登记着 *
* 所有系统合法的消息处理函数的地址。 *
* 2、ProcPCB[]下标中,0为系统保留,其余为用户 *
* 自定义。 *
* 3、用户需要自己通过编写函数并通过连接宏 *
* MSG_REGISTER_PROC_FUNCTION来注册合法消息处理 *
* 函数。 *
* 4、编程的时候,每增加一个静态的进程,就要增加一 *
* 次进程计数器MSG_Proc_Counter。 *
***********************************************************/
void MSGInit(void)
{
unsigned char n = 0;
for (n = 0;n<MSG_PROCESS_COUNT+1;n++)
{
ProcPCB[n].ProcIO = SYS_DEFAULT;
ProcPCB[n].Proc = NULLPROC;
ProcPCB[n].IfProcAlive = False;
}
MSG_REGISTER_PROC_FUNCTION
}
/***********************************************************
* 函数说明:消息创建函数 *
* 输入: 消息信息 *
* 输出: 消息指针 *
***********************************************************/
volatile MESSAGE *creatMSG(BOOL (*From)(volatile MESSAGE *MSG),BOOL (*To)(volatile MESSAGE *MSG),
unsigned char Flag,unsigned char MsgLen,unsigned char *Msg)
{
volatile MESSAGE *TempMSG = (volatile MESSAGE *)malloc(sizeof(volatile MESSAGE));
TempMSG->From = From;
TempMSG->To = To;
TempMSG->Flag = Flag;
TempMSG->MsgLen = MsgLen;
TempMSG->Msg = Msg;
return TempMSG;
}
/***********************************************************
* 函数说明:消息删除指令 *
* 输入: 需要释放消息的指针 *
***********************************************************/
void delMSG(volatile MESSAGE *MSG)
{
if (MSG != NULL)
{
free(MSG->Msg);
free((void *)MSG); //释放空间
}
}
/***********************************************************
* 函数说明:消息复制函数 *
* 输入: 源消息指针 *
* 输出: 目标消息指针 *
***********************************************************/
volatile MESSAGE *copyMSG(volatile MESSAGE *MSG)
{
unsigned char n = 0;
unsigned char Len = MSG->MsgLen;
volatile MESSAGE *TempMSG =(volatile MESSAGE *)malloc(sizeof(volatile MESSAGE));
unsigned char *TempMsgInfo = (unsigned char *)malloc(Len);
TempMSG->From = MSG->From;
TempMSG->To = MSG->To;
TempMSG->Flag = MSG->Flag;
TempMSG->Msg = TempMsgInfo;
TempMSG->MsgLen = MSG->MsgLen;
for (n = 0;n < Len;n++) //消息复制循环
{
TempMsgInfo[n] = MSG->Msg[n];
}
return TempMSG;
}
/***********************************************************
* 函数说明:系统默认消息处理函数 *
* 输入: 消息指针 *
***********************************************************/
BOOL SYS_DEFAULT(volatile MESSAGE *MSG)
{
MSG = MSG;
return True;
}
/***********************************************************
* 函数说明:消息调度函数 *
* 输入: 消息处理函数指针 *
* -------------------------------------------------------- *
* [注意事项] *
* 1、允许自定义默认的消息处理程序。 *
* 2、每一个有效的消息在传递给相应函数后,即便传递 *
* 成功,也会在返回调用以后被立即销毁,所以如果 *
* 需要使用该消息中的内容进行再次消息传递,需要 *
* 对消息进行复制,复制以后再进行传递,否则容易 *
* 造成野指针现象。 *
* 3、用户在整个过程中,无须自行删除消息。 *
***********************************************************/
void processMSG(BOOL (*Default)(volatile MESSAGE *MSG))
{
volatile MESSAGE *msg = NULL;
static unsigned char n = 0;
if (getMSG(&msg)) //没有消息
{
if (MSG_FLAG((msg->Flag)).MSG_FLAG_BROADCAST_BIT) //检测广播标志
{
for (n = 0;n<MSG_Proc_Counter;n++)
{
(*ProcPCB[n].ProcIO)(msg); //发送广播信息
}
}
else
{
if (!(*(msg->To))(msg)) //向指定函数发送消息
{
(*Default)(msg); //如果消息没有得到处理
}
}
delMSG(msg); //消息处理完后立即释放
}
if (ProcPCB[n].IfProcAlive) //处理进程
{
(*ProcPCB[n].Proc)();
}
n ++;
if (n >= MSG_Proc_Counter)
{
n = 0;
}
}
/***********************************************************
* 函数说明:添加消息到队列 *
* 输入: 消息指针 *
* 输出: 添加是否成功 *
***********************************************************/
BOOL addMSG(volatile MESSAGE *MSG)
{
if ((MSG_Head == MSG_Tail) && (MSG_Counter >= MSG_QUEUE_SIZE))
{
return False; //队列已满,添加失败
}
MSG_Queue[MSG_Tail] = MSG;
MSG_Tail++;
MSG_Counter++;
if (MSG_Tail >= MSG_QUEUE_SIZE)
{
MSG_Tail = 0;
}
return True;
}
/***********************************************************
* 函数说明:获取消息函数 *
* 输入: 消息指针 *
* 输出: 操作是否成功 *
***********************************************************/
BOOL getMSG(volatile MESSAGE **MSG)
{
if ((MSG_Head == MSG_Tail) && (MSG_Counter == NULL))
{
return False; //消息队列为空
}
(*MSG) = MSG_Queue[MSG_Head];
MSG_Head++;
MSG_Counter--;
if (MSG_Head >= MSG_QUEUE_SIZE)
{
MSG_Head = 0;
}
return True;
}
#endif
-----此内容被Gorgon Meducer于2006-06-17,19:26:31编辑过 |
|