共享内存和消息队列使用
/******************************************************************************
版权所有 (C), 2001-2011,
******************************************************************************
文 件 名 : drv_app_mem_master.c
版 本 号 : 初稿
作 者 : zhangjinlei
生成日期 : 2012年5月17日星期四
最近修改 :
功能描述 : 内存共享主机端主文件
函数列表 :
main
修改历史 :
1.日 期 : 2012年5月17日星期四
作 者 : zhangjinlei
修改内容 : 创建文件
******************************************************************************/
/*----------------------------------------------*
* 包含头文件 *
*----------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include "drv_app_common.h"
/*----------------------------------------------*
* 外部变量说明 *
*----------------------------------------------*/
/*----------------------------------------------*
* 外部函数原型说明 *
*----------------------------------------------*/
/*----------------------------------------------*
* 内部函数原型说明 *
*----------------------------------------------*/
/*----------------------------------------------*
* 全局变量 *
*----------------------------------------------*/
/*----------------------------------------------*
* 模块级变量 *
*----------------------------------------------*/
static int g_iReadSemID;
static int g_iWriteSemID;
/*----------------------------------------------*
* 常量定义 *
*----------------------------------------------*/
/*----------------------------------------------*
* 宏定义 *
*----------------------------------------------*/
#define DRV_APP_MSG_QUE_FILE_NAME "." /* 消息队列指定文件名 */
#define DRV_APP_SHARE_MEMORY_SIZE 81920 /* 共享内存的大小 */
/* BEGIN: Added by zhangjinlei, 2012/5/18 */
union semun {
int iValue;
struct semid_ds *pstBuffer;
unsigned short *pusArray;
}arg;
/*****************************************************************************
函 数 名 : DRV_APP_SEM_Creat
功能描述 : 创建信号量
输入参数 : IN ikey 信号量键值
输出参数 : 无
返 回 值 : int
调用函数 :
被调函数 :
修改历史 :
1.日 期 : 2012年5月18日星期五
作 者 : zhangjinlei
修改内容 : 新生成函数
*****************************************************************************/
int DRV_APP_SEM_Creat(IN const key_t ikey)
{
int iSemID;
union semun uSem;
uSem.pstBuffer = NULL;
uSem.pusArray= NULL;
uSem.iValue = 0;
/* 获取信号量ID号 */
iSemID = semget(ikey, 1, IPC_CREAT|0666);
if (-1 == iSemID)
{
printf("create semaphore error\n");
/* 推出进程 */
exit(-1);
}
/* 必须设置为1,否则第一次获取信号量失败 */
uSem.iValue = 1;
/* SETVAL: Set the value of semval to arg.val */
if (-1 == (semctl(iSemID, 0, SETVAL, uSem)))
{
printf("sem ctl error\n");
/* 推出进程 */
exit(-1);
}
return iSemID;
}
/*****************************************************************************
函 数 名 : DRV_APP_SEM_Delete
功能描述 : 删除信号量
输入参数 : int iSemID
输出参数 : 无
返 回 值 :
调用函数 :
被调函数 :
修改历史 :
1.日 期 : 2012年5月18日星期五
作 者 : zhangjinlei
修改内容 : 新生成函数
*****************************************************************************/
void DRV_APP_SEM_Delete(IN const int iSemID)
{
union semun uSem;
uSem.pstBuffer = NULL;
uSem.pusArray= NULL;
uSem.iValue = 0;
/* 删除信号量 */
if (-1 == (semctl(iSemID, 0, IPC_RMID, uSem)))
{
printf("sem ctl error\n");
/* 推出进程 */
exit(-1);
}
}
/*****************************************************************************
函 数 名 : DRV_APP_SEM_Passeren
功能描述 : 信号量使能
输入参数 : iSemID 信号量
输出参数 : 无
返 回 值 : int
调用函数 :
被调函数 :
修改历史 :
1.日 期 : 2012年5月18日星期五
作 者 : zhangjinlei
修改内容 : 新生成函数
*****************************************************************************/
int DRV_APP_SEM_Passeren(IN const int iSemID)
{
struct sembuf stSops;
stSops.sem_num = 0;
stSops.sem_op = -1;
stSops.sem_flg = SEM_UNDO;
/*
* 如果sem_op为正数,semop函数将该值加到相应的信号量元素中,
* 并唤醒所有等待元素增1的进程。如果sem_op为0而信号量的值不为0,
* semop将阻塞调用进程并增加那个元素的等零进程个数。如果sem_op为负数,
* semop将该值加到相应的信号量元素中(只要结果不为负数),如结果为负数,
* semop将阻塞进程等待信号量元素值增加
*/
if (-1 == (semop(iSemID, &stSops, 1)))
{
printf("sem release error\n");
return -1;
}
return ERROR_SUCCESS;
}
/*****************************************************************************
函 数 名 : DRV_APP_SEM_Release
功能描述 : 信号量释放
输入参数 : iSemID 信号量
输出参数 : 无
返 回 值 : int
调用函数 :
被调函数 :
修改历史 :
1.日 期 : 2012年5月18日星期五
作 者 : zhangjinlei
修改内容 : 新生成函数
*****************************************************************************/
int DRV_APP_SEM_Release(int iSemID)
{
struct sembuf stSops;
stSops.sem_num = 0;
stSops.sem_op = 1;
stSops.sem_flg = SEM_UNDO;
/*
* 如果sem_op为正数,semop函数将该值加到相应的信号量元素中,
* 并唤醒所有等待元素增1的进程。如果sem_op为0而信号量的值不为0,
* semop将阻塞调用进程并增加那个元素的等零进程个数。如果sem_op为负数,
* semop将该值加到相应的信号量元素中(只要结果不为负数),如结果为负数,
* semop将阻塞进程等待信号量元素值增加
*/
if (-1 == (semop(iSemID, &stSops, 1)))
{
printf("sem release error\n");
return -1;
}
return ERROR_SUCCESS;
}
/* END: Added by zhangjinlei, 2012/5/18 PN: */
/*****************************************************************************
函 数 名 : main
功能描述 : 内存共享主机端主程序
输入参数 : void
输出参数 : 无
返 回 值 : int
调用函数 :
被调函数 :
修改历史 :
1.日 期 : 2012年5月17日星期四
作 者 : zhangjinlei
修改内容 : 新生成函数
*****************************************************************************/
int main(IN const int iargc, OUT char **ppargv)
{
key_t iKey; /* 消息队列对应的键值 */
key_t iReadSemKey; /* 消息队列对应的键值 */
key_t iWriteSemKey; /* 消息队列对应的键值 */
int iMsgID; /* 消息队列对应的ID值 */
const char cSendMsg[40]= "service send msg data!";
int iRet;
void *pTempAdd = NULL;
(void)iargc;
(void)ppargv;
printf("[app]mem share page size=%d\n", getpagesize());
if ((iKey = ftok(DRV_APP_MSG_QUE_FILE_NAME, 's')) == -1)
{
printf("[app]mem share Creat Key Error, ikey = %d, line = %d\n", iKey, __LINE__);
return ERROR_FAILED;
}
/* BEGIN: Added by zhangjinlei, 2012/5/18 */
if ((iReadSemKey = ftok(DRV_APP_MSG_QUE_FILE_NAME, 'r')) == -1)
{
printf("[app]sem Creat Key Error, ikey = %d, line = %d\n", iReadSemKey, __LINE__);
return ERROR_FAILED;
}
if ((iWriteSemKey = ftok(DRV_APP_MSG_QUE_FILE_NAME, 'w')) == -1)
{
printf("[app]sem Creat Key Error, ikey = %d, line = %d\n", iWriteSemKey, __LINE__);
return ERROR_FAILED;
}
/* END: Added by zhangjinlei, 2012/5/18 PN: */
/* 创建了20KB大小的共享内存空间 */
if((iMsgID = shmget(iKey, DRV_APP_SHARE_MEMORY_SIZE, 0666|IPC_CREAT )) == -1)
{
printf("Creat iMsgID Error, iMsgID = %d, line = %d\n", iMsgID, __LINE__);
return ERROR_FAILED;
}
/* 锁定该区域的内存 */
iRet = shmctl(iMsgID, SHM_LOCK, 0);
if(0 != iRet )
{
printf("[app]locked memory share failed, iRet = %d, line = %d\n", iRet, __LINE__);
return ERROR_FAILED;
}
pTempAdd = shmat(iMsgID, ( const void* )0, 0);
if (NULL == pTempAdd)
{
printf("[app]Get memory share failed, line = %d\n", __LINE__);
return ERROR_FAILED;
}
/* BEGIN: Added by zhangjinlei, 2012/5/18 */
g_iReadSemID = DRV_APP_SEM_Creat(iReadSemKey);
g_iWriteSemID = DRV_APP_SEM_Creat(iWriteSemKey);
/* END: Added by zhangjinlei, 2012/5/18 PN: */
for (; ;)
{
/* BEGIN: Added by zhangjinlei, 2012/5/18 */
(void)DRV_APP_SEM_Passeren(g_iWriteSemID);
/* END: Added by zhangjinlei, 2012/5/18 PN: */
(void)memcpy(pTempAdd, cSendMsg, sizeof(cSendMsg));
printf("[app]DRV_APP_SEM_Passeren , line = %d\n", __LINE__);
/* BEGIN: Added by zhangjinlei, 2012/5/18 */
(void)DRV_APP_SEM_Release(g_iReadSemID);
/* END: Added by zhangjinlei, 2012/5/18 PN: */
(void)sleep(2);
}
#if 0
/* BEGIN: Added by zhangjinlei, 2012/5/18 */
v(semid);
/* END: Added by zhangjinlei, 2012/5/18 PN: */
iRet = shmdt(pTempAdd);
if (0 != iRet)
{
printf("[app]Memory detached failed %d, line = %d\n", iRet, __LINE__);
return ERROR_FAILED;
}
#endif
}
服务器端:
/******************************************************************************
版权所有 (C), 2001-2011,
******************************************************************************
文 件 名 : drv_app_mem_slave.c
版 本 号 : 初稿
作 者 : zhangjinlei
生成日期 : 2012年5月16日星期三
最近修改 :
功能描述 : 内存共享客户端函数
函数列表 :
main
修改历史 :
1.日 期 : 2012年5月16日星期三
作 者 : zhangjinlei
修改内容 : 创建文件
******************************************************************************/
/*----------------------------------------------*
* 包含头文件 *
*----------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include "drv_app_common.h"
/*----------------------------------------------*
* 外部变量说明 *
*----------------------------------------------*/
/*----------------------------------------------*
* 外部函数原型说明 *
*----------------------------------------------*/
/*----------------------------------------------*
* 内部函数原型说明 *
*----------------------------------------------*/
/*----------------------------------------------*
* 全局变量 *
*----------------------------------------------*/
static int g_iReadSemID;
static int g_iWriteSemID;
/*----------------------------------------------*
* 模块级变量 *
*----------------------------------------------*/
/*----------------------------------------------*
* 常量定义 *
*----------------------------------------------*/
/*----------------------------------------------*
* 宏定义 *
*----------------------------------------------*/
#define DRV_APP_MSG_QUE_FILE_NAME "." /* 消息队列指定文件名 */
#define DRV_APP_SHARE_MEMORY_SIZE 81920 /* 共享内存的大小 */
/* BEGIN: Added by zhangjinlei, 2012/5/18 */
union semun {
int iValue;
struct semid_ds *pstBuffer;
unsigned short *pusArray;
}arg;
/*****************************************************************************
函 数 名 : DRV_APP_SEM_Creat
功能描述 : 创建信号量
输入参数 : IN ikey 信号量键值
输出参数 : 无
返 回 值 : int
调用函数 :
被调函数 :
修改历史 :
1.日 期 : 2012年5月18日星期五
作 者 : zhangjinlei
修改内容 : 新生成函数
*****************************************************************************/
int DRV_APP_SEM_Creat(IN const key_t ikey)
{
int iSemID;
union semun uSem;
uSem.pstBuffer = NULL;
uSem.pusArray= NULL;
uSem.iValue = 0;
/* 获取信号量ID号 */
iSemID = semget(ikey, 1, IPC_CREAT|0666);
if (-1 == iSemID)
{
printf("create semaphore error\n");
/* 推出进程 */
exit(-1);
}
/* 必须设置为1,否则第一次获取信号量失败 */
uSem.iValue = 1;
/* SETVAL: Set the value of semval to arg.val */
if (-1 == (semctl(iSemID, 0, SETVAL, uSem)))
{
printf("sem ctl error\n");
/* 推出进程 */
exit(-1);
}
return iSemID;
}
//删除信号量
/*****************************************************************************
函 数 名 : DRV_APP_SEM_Delete
功能描述 : 删除信号量
输入参数 : int iSemID
输出参数 : 无
返 回 值 :
调用函数 :
被调函数 :
修改历史 :
1.日 期 : 2012年5月18日星期五
作 者 : zhangjinlei
修改内容 : 新生成函数
*****************************************************************************/
void DRV_APP_SEM_Delete(IN const int iSemID)
{
union semun uSem;
uSem.pstBuffer = NULL;
uSem.pusArray= NULL;
uSem.iValue = 0;
/* 删除信号量 */
if (-1 == (semctl(iSemID, 0, IPC_RMID, uSem)))
{
printf("sem ctl error\n");
/* 推出进程 */
exit(-1);
}
}
/*****************************************************************************
函 数 名 : DRV_APP_SEM_Passeren
功能描述 : 信号量使能
输入参数 : iSemID 信号量
输出参数 : 无
返 回 值 : int
调用函数 :
被调函数 :
修改历史 :
1.日 期 : 2012年5月18日星期五
作 者 : zhangjinlei
修改内容 : 新生成函数
*****************************************************************************/
int DRV_APP_SEM_Passeren(IN const int iSemID)
{
struct sembuf stSops;
stSops.sem_num = 0;
stSops.sem_op = -1;
stSops.sem_flg = SEM_UNDO;
/*
* 如果sem_op为正数,semop函数将该值加到相应的信号量元素中,
* 并唤醒所有等待元素增1的进程。如果sem_op为0而信号量的值不为0,
* semop将阻塞调用进程并增加那个元素的等零进程个数。如果sem_op为负数,
* semop将该值加到相应的信号量元素中(只要结果不为负数),如结果为负数,
* semop将阻塞进程等待信号量元素值增加
*/
if (-1 == (semop(iSemID, &stSops, 1)))
{
printf("sem release error\n");
return -1;
}
return ERROR_SUCCESS;
}
/*****************************************************************************
函 数 名 : DRV_APP_SEM_Release
功能描述 : 信号量释放
输入参数 : iSemID 信号量
输出参数 : 无
返 回 值 : int
调用函数 :
被调函数 :
修改历史 :
1.日 期 : 2012年5月18日星期五
作 者 : zhangjinlei
修改内容 : 新生成函数
*****************************************************************************/
int DRV_APP_SEM_Release(int iSemID)
{
struct sembuf stSops;
stSops.sem_num = 0;
stSops.sem_op = 1;
stSops.sem_flg = SEM_UNDO;
/*
* 如果sem_op为正数,semop函数将该值加到相应的信号量元素中,
* 并唤醒所有等待元素增1的进程。如果sem_op为0而信号量的值不为0,
* semop将阻塞调用进程并增加那个元素的等零进程个数。如果sem_op为负数,
* semop将该值加到相应的信号量元素中(只要结果不为负数),如结果为负数,
* semop将阻塞进程等待信号量元素值增加
*/
if (-1 == (semop(iSemID, &stSops, 1)))
{
printf("sem release error\n");
return -1;
}
return ERROR_SUCCESS;
}
/* END: Added by zhangjinlei, 2012/5/18 PN: */
/*****************************************************************************
函 数 名 : main
功能描述 : 内存共享客户端主函数
输入参数 : void
输出参数 : 无
返 回 值 : ERROR_SUCCESS :表示函数执行成功
ERROR_FAILED :表示函数执行失败
修改历史 :
1.日 期 : 2012年5月16日星期三
作 者 : zhangjinlei
修改内容 : 新生成函数
*****************************************************************************/
int main(IN const int iargc, OUT char **ppargv)
{
key_t iKey; /* 消息队列对应的键值 */
key_t iReadSemKey; /* 消息队列对应的键值 */
key_t iWriteSemKey; /* 消息队列对应的键值 */
int iMsgID; /* 消息队列对应的ID值 */
char cSendMsg[40]= "service send msg data!";
int iRet;
const void *pTempAdd = NULL;
(void)iargc;
(void)ppargv;
printf("[app]mem share page size=%d\n", getpagesize());
if ((iKey = ftok(DRV_APP_MSG_QUE_FILE_NAME, 's')) == -1)
{
printf("[app]mem share Creat Key Error, ikey = %d, line = %d\n", iKey, __LINE__);
return ERROR_FAILED;
}
/* BEGIN: Added by zhangjinlei, 2012/5/18 */
if ((iReadSemKey = ftok(DRV_APP_MSG_QUE_FILE_NAME, 'r')) == -1)
{
printf("[app]sem Creat Key Error, iReadSemKey = %d, line = %d\n", iReadSemKey, __LINE__);
return ERROR_FAILED;
}
if ((iWriteSemKey = ftok(DRV_APP_MSG_QUE_FILE_NAME, 'w')) == -1)
{
printf("[app]sem Creat Key Error, iWriteSemKey = %d, line = %d\n", iWriteSemKey, __LINE__);
return ERROR_FAILED;
}
/* END: Added by zhangjinlei, 2012/5/18 PN: */
/* 创建了20KB大小的共享内存空间 */
if((iMsgID = shmget(iKey, DRV_APP_SHARE_MEMORY_SIZE, 0666|IPC_CREAT )) == -1)
{
printf("Creat iMsgID Error, iMsgID = %d, line = %d\n", iMsgID, __LINE__);
return ERROR_FAILED;
}
/* 锁定该区域的内存 */
iRet = shmctl(iMsgID, SHM_LOCK, 0);
if(0 != iRet )
{
printf("[app]locked memory share failed, iRet = %d, line = %d\n", iRet, __LINE__);
return ERROR_FAILED;
}
pTempAdd = shmat(iMsgID, ( const void* )0, 0);
if (NULL == pTempAdd)
{
printf("[app]Get memory share failed, line = %d\n", __LINE__);
return ERROR_FAILED;
}
/* BEGIN: Added by zhangjinlei, 2012/5/18 */
g_iReadSemID = DRV_APP_SEM_Creat(iReadSemKey);
g_iWriteSemID = DRV_APP_SEM_Creat(iWriteSemKey);
/* END: Added by zhangjinlei, 2012/5/18 PN: */
for (; ;)
{
/* BEGIN: Added by zhangjinlei, 2012/5/18 */
(void)DRV_APP_SEM_Passeren(g_iReadSemID);
/* END: Added by zhangjinlei, 2012/5/18 PN: */
(void)memcpy(cSendMsg, pTempAdd, sizeof(cSendMsg));
/* BEGIN: Added by zhangjinlei, 2012/5/18 */
(void)DRV_APP_SEM_Release(g_iWriteSemID);
/* END: Added by zhangjinlei, 2012/5/18 PN: */
printf("[app]read memory buffer msg is %s, line = %d\n", cSendMsg, __LINE__);
(void)sleep(2);
}
#if 0
iRet = shmdt(pTempAdd);
if (0 != iRet)
{
printf("[app]Memory detached failed %d, line = %d\n", iRet, __LINE__);
return ERROR_FAILED;
}
#endif
}
公共文件:
/******************************************************************************
版权所有 (C), 2001-2011,
******************************************************************************
文 件 名 : drv_app_common.h
版 本 号 : 初稿
作 者 : zhangjinlei
生成日期 : 2012年5月16日星期三
最近修改 :
功能描述 : drv_app_common.h 的头文件
函数列表 :
修改历史 :
1.日 期 : 2012年5月16日星期三
作 者 : zhangjinlei
修改内容 : 创建文件
******************************************************************************/
#ifndef __DRV_APP_COMMON_H__
#define __DRV_APP_COMMON_H__
#ifdef __cplusplus
#if __cplusplus
extern "C"{
#endif
#endif /* __cplusplus */
/*----------------------------------------------*
* 包含头文件 *
*----------------------------------------------*/
/*----------------------------------------------*
* 外部变量说明 *
*----------------------------------------------*/
/*----------------------------------------------*
* 外部函数原型说明 *
*----------------------------------------------*/
/*----------------------------------------------*
* 内部函数原型说明 *
*----------------------------------------------*/
/*----------------------------------------------*
* 全局变量 *
*----------------------------------------------*/
/*----------------------------------------------*
* 模块级变量 *
*----------------------------------------------*/
/*----------------------------------------------*
* 常量定义 *
*----------------------------------------------*/
/*----------------------------------------------*
* 宏定义 *
*----------------------------------------------*/
#define IN
#define OUT
#define INOUT
#define ERROR_SUCCESS 0
#define ERROR_FAILED 1
#define DRV_APP_MSG_QUE_REPORT_TYPE 0x01 /* 报站器数据消息 */
#define DRV_APP_MSG_QUE_REPORT_BACK 0x02 /* App 模块回应报站器消息 */
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* __cplusplus */
#endif /* __DRV_APP_COMMON_H__ */