linux 共享内存消息队列使用

共享内存和消息队列使用

/******************************************************************************

                  版权所有 (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__ */


 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值