Posic IPC API使用

Posic IPC API使用--早年写的一部分代码 

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

 * Copyright 
 * All rights reserved
 *
 * 文件名称: posix_ipcs.h
 * 文件标示:
 * 摘    要: posix IPC
 * 线程安全: 是
 *
 * 当前版本: 1.0
 * 作    者: shenyu
 * 完成日期: 2010-9-8 10:12:09
 *
 * 备注
********************************************************************/
#ifndef _POSIX_IPCS_H_
#define _POSIX_IPCS_H_


#include "basic.h"
#include "datetime.h"
#include <mqueue.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <fcntl.h>  




#define MQ_BLOCK     0  //阻塞消息队列
#define MQ_NON_BLOCK 1  //非阻塞消息队列


#define LEN_POSIX_MSG_MAX 2048  //最大消息长度


//Posix 消息队列
class CPosixMQ
{
public:
    CPosixMQ(const char * pszIpcName , int iDebugOn = DEBUG_OFF);
    CPosixMQ(const char * pszIpcName , long lMaxMsgSize,long lMaxMsgCnt,int iDebugOn = DEBUG_OFF);
    virtual ~CPosixMQ();
    
    static long POSIX_MQ_OPEN_MAX(); //单个进程能打开的最大消息队列个数
    static long POSIX_MQ_PRIO_MAX(); //任意消息队列最大优先级数
    
    bool Exist();   //消息队列是否已经存在 存在则返回true 否则返回false
    void SetIpcName(const char * pszIpcName);    //设置消息队列关联的文件名 
   
    bool SetAttr(int iBlockFlag  = MQ_BLOCK); //设置消息队列的属性 (只能设置组设和非阻塞属性 大小在创建的时候已经确定)
    bool GetAttr(long * plMaxMsgCnt,long * plMaxMsgSize,long * plCurMsgs);//获取消息队列属性


    bool SendMsg(char *pszMsgData, int iMsgLen,unsigned int  uiPrio, int iTimeOut = INFINITE) const;//数据发送到消息队列
    bool RecvMsg(char *pszMsgData, int *piMsgLen,unsigned int * puiPrio, int iTimeOut = INFINITE) const;//数据从消息队列读出
   
    bool Open(int iCreateMSQ = CREATE_FORCE );     //打开或者创建不存在的队列  
    bool Close();    //关闭打开的消息队列
   
    int Clear() ;    //清空消息队列
    bool Remove();   //删除消息队列
    int MsgCnt() ;   //当前消息个数


    void SetDeBugOn(){m_iDebugOn = DEBUG_ON; }
    
protected:
private:
    mqd_t m_mqd;                //posix 消息队列标识
    mq_attr m_attr;             //消息队列属性
    char m_szIpcName[LEN_FILE_NAME+1];    // 消息队列关联的名称
    int m_iDebugOn;             // 0 -表示不打开调试日志 1-表示打开调试日志
};


//Posix 共享内存
class CPosixShm
{
public:
    CPosixShm(const char * pszIpcName ,int iDebugOn = DEBUG_OFF);
    virtual~CPosixShm();


    void * Alloc(int iSize);   //申请共享内存


    bool Attach();                          //将进城与共享内存关联
    void Detach();                          //删除进程与共享内存的关联


    bool Exist() ;   //消息队列是否已经存在 存在则返回true 否则返回false
    void SetIpcName(const char * pszIpcName);    //设置共享内存关联的文件名 


    bool Open(int iCreateShm = CREATE_FORCE );     //打开或者创建共享内存
    bool Close();    //关闭共享内存的关联
    
    bool Remove();   //删除共享内存
    int Size() ;     //当前共享内存的大小


    void *GetShmPoint() const {return m_pvShmHead;}    //获取共享内存块指针


    void SetDeBugOn(){m_iDebugOn = DEBUG_ON; }
protected:
private:
    int m_iShmId;                               //共享内存
    char m_szIpcName[LEN_FILE_NAME+1];                     // 共享内存关联的名称
    int m_iDebugOn;                              // 0 -表示不打开调试日志 1-表示打开调试日志
    void *m_pvShmHead; //指向共享内存块的首指针
};


/********************************************************************
 * Copyright 
 * All rights reserved
 *
 * 文件名称: posix_ipcs.h
 * 文件标示:
 * 摘    要: posix IPC
 * 线程安全: 是
 *
 * 当前版本: 1.0
 * 作    者: shenyu
 * 完成日期: 2010-9-8 10:12:09
 *
 * 备注
    消息队列默认 消息个数10 消息大小 8192
    $ cat /proc/sys/fs/mqueue/msgsize_max
    8192
    $ cat /proc/sys/fs/mqueue/queues_max
    256
    $ cat /proc/sys/fs/mqueue/msg_max
    10


    /etc/sysctl.conf


    #add by shenyu Posix Setting
    fs.mqueue.msg_max=10000
    fs.mqueue.msgsize_max=8192


    消息队列的容量指 ulimit -q 819200
    修改该值:ulimit -q 8192000(仅仅root能使用好像)
    消息队列大小*消息长度+某个常量(系统)  < 819200 (大概为600*1024)
********************************************************************/
#include "posix_ipcs.h"


/**********************************Posix 消息队列*****************************************************/
/*
功能:构造函数(用于打开已经存在的消息队列)
参数:无
返回值:无
*/
CPosixMQ::CPosixMQ(const char * pszIpcName ,int iDebugOn )
{


    SetIpcName(pszIpcName);
    m_mqd = (mqd_t)-1;
    memset(&m_attr,0,sizeof(m_attr));
    m_iDebugOn = iDebugOn;
}
/*
功能:构造函数(用于创建或者打开消息队列) 
参数:
    const char * pszIpcName[in] IPC名称
    long lMaxMsgSize[in] 一个消息的最多字节数
    long lMaxMsgCnt[in] 消息的最多个数
    int iDebugOn[in] 调试 
返回值:无
备注:
    创建时只关注消息大小和消息的个数,而阻塞和非阻塞需要用mq_setattr来设置修改,它忽略其他参数
*/
CPosixMQ::CPosixMQ(const char * pszIpcName ,long lMaxMsgSize, long lMaxMsgCnt,int iDebugOn )
{
    //IPC名称
    SetIpcName(pszIpcName);


    //消息队列属性 消息队列默认为阻塞模式
    memset(&m_attr,0,sizeof(m_attr));
    m_attr.mq_maxmsg = lMaxMsgCnt;
    m_attr.mq_msgsize = lMaxMsgSize;
    m_attr.mq_flags = 0;


    m_mqd = (mqd_t)-1;
    m_iDebugOn = iDebugOn;
}


/*
功能:析构函数
参数:无
返回值:无
*/
CPosixMQ::~CPosixMQ()
{
}
/*
功能:单个进程能打开的最大消息队列个数 -1可能表示无明确定义 (POSIX要求至少为8)
参数:无
返回值:
    单个进程能打开的最大消息队列个数
*/
long CPosixMQ::POSIX_MQ_OPEN_MAX()   
{
    return sysconf(_SC_MQ_OPEN_MAX);
}
/*
功能:任意消息队列最大优先级数 -1可能表示无明确定义  (POSIX要求至少为32)
参数:无
返回值:
    任意消息队列最大优先级数
*/
long CPosixMQ::POSIX_MQ_PRIO_MAX()   
{
    return sysconf(_SC_MQ_PRIO_MAX);
}


/*
功能:设置与消息队列关联的文件名(其他函数调用的前提)
参数:
    char * pszIpcName[in] Posix 消息队列名称
返回值:
    无   
*/
void CPosixMQ::SetIpcName(const char * pszIpcName)
{
    memset(m_szIpcName,0,sizeof(m_szIpcName));
    snprintf(m_szIpcName,sizeof(m_szIpcName),"/%s.msq",pszIpcName);
}


/*
功能:设置消息队列的属性 (创建时只关注消息大小和消息的个数,而阻塞和非阻塞需要用mq_setattr来设置修改,它忽略其他参数)
参数:


    int iBlockFlag  [in] 阻塞或者非阻塞
返回值:
    true 成功
    false 设置失败
*/
bool CPosixMQ::SetAttr(int iBlockFlag /* = MQ_BLOCK */)
{
    int iRet = -1;
    //忽略其他参数
    m_attr.mq_flags = (iBlockFlag == MQ_NON_BLOCK) ? O_NONBLOCK:0;


    iRet = mq_setattr(m_mqd,&m_attr,NULL);
    if (iRet != 0)
    {
        return false;
    }   
    return true;  
}


/*
功能:获取消息队列的属性 (创建时只关注消息大小和消息的个数,而阻塞和非阻塞需要用mq_setattr来设置修改,它忽略其他参数)
参数:
    long * plMaxMsgCnt[out] 最多消息个数
    long * plMaxMsgSize[out]最大单个消息大小
    long * plCurMsgs[out] 当前消息个数
返回值:
    bool 成功
    false 失败
*/
bool CPosixMQ::GetAttr(long * plMaxMsgCnt,long * plMaxMsgSize,long * plCurMsgs)
{
    int iRet = -1; 
    mq_attr attr;             


    if(m_mqd == (mqd_t)-1)
    {
        return false;
    }
    memset(&attr,0,sizeof(attr));
    iRet = mq_getattr(m_mqd,&attr);
    if (iRet != 0)
    {
        return false;
    }
    
    *plMaxMsgCnt = attr.mq_maxmsg;
    *plMaxMsgSize = attr.mq_msgsize;
    *plCurMsgs = attr.mq_curmsgs;


    return true;
}
/*
功能:打开或者创建不存在的队列
参数:
    int iCreateMSQ[in] 是否强制创建队列
返回值:
    true 成功
    false 失败
*/   
bool CPosixMQ::Open(int iCreateMSQ )
{
    int iRet = -1;
    int iFlags;


    if (m_szIpcName[0] == '\0')
    {
        return false;
    }
    
    if (iCreateMSQ == CREATE_FORCE)
    {
        iFlags = O_RDWR | O_CREAT;
    }
    else
    {
         iFlags = O_RDWR ;
    }
    
    //未设置属性
    if (m_attr.mq_maxmsg == 0)
    {
        m_mqd = mq_open(m_szIpcName, iFlags,0666,NULL);
    }
    else
    {
        m_mqd = mq_open(m_szIpcName, iFlags,0666,&m_attr);
    }
    if (m_mqd == (mqd_t)-1)
    {
        if (m_iDebugOn == DEBUG_ON)
        {
            perror("mq_open:");
            printf("(%s-%d) mq_open fail! [%s] ,iRet = [%d]\n",FILELINE,m_szIpcName,iRet);
        }
        return false;
    }


    if (m_iDebugOn == DEBUG_ON)
    {
        printf("(%s-%d) mq_open succ!\n",FILELINE);
    }
    return true;


}
/*
功能:关闭打开的消息队列
参数:无
返回值:
    SUCC 成功删除
    FAIL 删除失败
*/   
bool CPosixMQ::Close()
{
    return (mq_close(m_mqd) == (mqd_t)0);
}


/*
功能:消息队列是否已经存在 (需要先设置消息队列对应的文件名称)
参数:无
返回值:
    存在则返回true 
    否则返回false
*/   
bool CPosixMQ::Exist()
{   
    int iRet = -1;
    
    if (!Open(CREATE_NO_FORCE))
    {
        return false;
    }
    
    Close();
    return true;
}
/*
功能:清空消息队列里的消息
参数:无
返回值:
    num 清除的消息个数
    FAIL 处理失败
*/   
int CPosixMQ::Clear() 
{
    int iRet = -1,iCnt = 0;
    int iFlags;
    char szMsgTmp[LEN_POSIX_MSG_MAX+1];
    unsigned int uiPrio;
    struct timespec timewake;


    if ( m_mqd == (mqd_t)-1 || m_szIpcName[0] == '\0' )
    {
        return FAIL;
    }


    //清空消息队列  
    while (1)
    {
        CDateTimeH::AbsTimeFromNow(0,&timewake);
        memset(szMsgTmp,0,sizeof(szMsgTmp));
        iRet = mq_timedreceive(m_mqd, szMsgTmp,LEN_POSIX_MSG_MAX,&uiPrio,&timewake);
        if(iRet < 0 )
        {
            break;
        }
        iCnt++;
    }
    return iCnt;
}


/*
功能:删除消息队列
参数:无
返回值:
    SUCC 成功删除
    FAIL 删除失败
*/   
bool CPosixMQ::Remove()
{
    return (mq_unlink(m_szIpcName) == (mqd_t)0);
}


/*
功能:当前消息个数
参数:无
返回值:
    >=0 当前消息的个数
*/   
int CPosixMQ::MsgCnt()
{
    int iRet = -1;
    struct mq_attr attr;
    
    memset(&attr,0,sizeof(attr));
    iRet = mq_getattr(m_mqd,&attr);
    if (iRet != 0 )
    {
        return -1;
    }
    
    if (m_iDebugOn == DEBUG_ON)
    {
        printf("(%s-%d) mq_flags = %ld,max msgs = %ld ,max bytes one msg = %ld,current on queue = %ld\n",
            FILELINE,attr.mq_flags, attr.mq_maxmsg,attr.mq_msgsize,attr.mq_curmsgs);
    }
    return attr.mq_curmsgs;
}


/*
功能:写入消息队列数据 (不能像system v消息队列一样 每次都打开 每次都打开 则文件描述符加1)             
参数:                                            
char *pszMsgData[in]写入的消息数据    
int iMsgLen[in]消息数据长度      
unsigned int  uiPrio[in] 消息优先级 1-32     
int iTimeOut[in]超时时间(单位ms)<0 阻塞等待,=0 非阻塞等待,>0超时控制                                          
返回:                                         
SUCC 成功              
< 0    失败              
*/
bool CPosixMQ::SendMsg(char *pszMsgData, int iMsgLen,unsigned int  uiPrio, int iTimeOut /* = INFINITE */) const
{
    int iRet = -1;
    int iFlags;
    
    if ( m_mqd == (mqd_t)-1 || m_szIpcName[0] == '\0' )
    {
        return false;
    }
    
    //发送数据 无超时设置 则阻塞发送
    if (iTimeOut == INFINITE)
    {
        iRet = mq_send(m_mqd, pszMsgData,iMsgLen,uiPrio);
        if(iRet != 0 )
        {
            if (m_iDebugOn == DEBUG_ON)
            {
                perror("mq_send:");
                printf("(%s-%d) mq_send [%d] Faild!errno = [%d]\n",FILELINE,m_mqd,errno);
            }
            return false;
        }
    }
    else
    {
        struct timespec timewake;
        CDateTimeH::AbsTimeFromNow(iTimeOut,&timewake);


        iRet = mq_timedsend(m_mqd, pszMsgData,iMsgLen,uiPrio,&timewake);
        if(iRet != 0 )
        {
            if (m_iDebugOn == DEBUG_ON)
            {
                perror("mq_send:");
                printf("(%s-%d) mq_timedsend [%d] Faild!errno = [%d]\n",FILELINE,m_mqd,errno);
            }
            return false;
        }
    }
    return true;
}
/*
功能: 读取消息队列数据  (不能像system v消息队列一样 每次都打开 每次都打开 则文件描述符加1)       
参数:                                            
char *pszMsgData[out]写入的消息数据    
int iMsgLen[out]消息数据长度      
unsigned int * puiPrio[out]消息优先级       
int iTimeOut[in]超时时间(秒)<0 阻塞等待,=0 非阻塞等待,>0超时控制                                                
返回:                                         
SUCC 成功              
< 0    失败              
*/
bool CPosixMQ::RecvMsg(char *pszMsgData, int *piMsgLen,unsigned int * puiPrio, int iTimeOut /* = INFINITE */) const
{
    int iRet = -1;
    int iFlags;
    
    if ( m_mqd == (mqd_t)-1 || m_szIpcName[0] == '\0' )
    {
        return false;
    }


    //发送数据 无超时设置 则阻塞接受
    if (iTimeOut == INFINITE)
    {
        iRet = mq_receive(m_mqd, pszMsgData,LEN_POSIX_MSG_MAX,puiPrio);
        if(iRet < 0 )
        {
            if (m_iDebugOn == DEBUG_ON)
            {
                perror("mq_send:");
                printf("(%s-%d) mq_send [%d] Faild!errno = [%d]\n",FILELINE,m_mqd,errno);
            }
            return false;
        }
    }
    else
    {
        struct timespec timewake;
        
        CDateTimeH::AbsTimeFromNow(iTimeOut,&timewake);
        iRet = mq_timedreceive(m_mqd, pszMsgData,LEN_POSIX_MSG_MAX,puiPrio,&timewake);
        if(iRet < 0 )
        {
            if (m_iDebugOn == DEBUG_ON)
            {
                perror("mq_send:");
                printf("(%s-%d) mq_timedsend [%d] Faild!errno = [%d]\n",FILELINE,m_mqd,errno);
            }
            return false;
        }
    }
    *piMsgLen = iRet;
    return true;
}


/**********************************Posix 消息队列*****************************************************/




/**********************************Posix 共享内存*****************************************************/


/*
功能:构造函数
参数:无
返回值:无
*/
CPosixShm::CPosixShm(const char * pszIpcName , int iDebugOn )
{
    SetIpcName(pszIpcName);
    m_iShmId = -1;
    m_pvShmHead = NULL;
    m_iDebugOn = iDebugOn;
}
/*
功能:析构函数
参数:无
返回值:无
*/
CPosixShm::~CPosixShm()
{
    m_iShmId = -1;
    memset(m_szIpcName,0,sizeof(m_szIpcName));
    m_pvShmHead = NULL;
}


/*
功能:设置与共享内存关联的文件名(其他函数调用的前提)
参数:
    char * pszIpcName[in] Posix 共享内存名称
返回值:
    无   
*/
void CPosixShm::SetIpcName(const char * pszIpcName)
{
    memset(m_szIpcName,0,sizeof(m_szIpcName));
    snprintf(m_szIpcName,sizeof(m_szIpcName),"/%s.shm",pszIpcName);
}


/*
功能:共享内存是否已经存在 (需要先设置共享内存对应的文件名称)
参数:无
返回值:
    存在则返回true 
    否则返回false
*/   
bool CPosixShm::Exist() 
{   
    if (!Open(CREATE_NO_FORCE))
    {
        return false;
    }
    Close();
    return true;
}
/*
功能:打开或者创建不存在的共享内存
参数:
    int iCreateShm[in] 是否强制创建共享内存
返回值:
    SUCC 成功删除
    FAIL 删除失败
*/   
bool CPosixShm::Open(int iCreateShm )
{
    int iRet = -1;
    int iFlags;


    if (m_szIpcName[0] == '\0')
    {
        return false;
    }


    if (iCreateShm == CREATE_FORCE)
    {
        iFlags = O_RDWR | O_CREAT;
    }
    else
    {
        iFlags = O_RDWR ;
    }


    iRet = shm_open(m_szIpcName,iFlags,0666);
    if (iRet < 0 )
    {
        if (m_iDebugOn == DEBUG_ON)
        {
            perror("shm_open:");
            printf("(%s-%d) shm_open [%d] Faild!errno = [%d]\n",FILELINE,iRet,errno);
        }   
        return false;
    }
    m_iShmId = iRet;
    
    return true;
}


/*
功能:关闭打开的共享内存
参数:无
返回值:
    SUCC 成功删除
    FAIL 删除失败
*/   
bool CPosixShm::Close()
{
    return (close(m_iShmId) == 0);
}
/*
功能:当前共享内存的大小
参数:无
返回值:
    >=0 当前共享内存的大小
    <0 获取共享内存大小失败
*/   
int CPosixShm::Size()
{
    int iRet = -1;
    struct stat shmstate;


    if (!Open(CREATE_NO_FORCE))
    {
        return -1;
    }   


    iRet = fstat(m_iShmId,&shmstate);
    if (iRet != 0)
    {
        Close();
        return -1;
    }
    Close();
    return shmstate.st_size;
}
/*
功能:删除共享内存
参数:无
返回值:
    SUCC 成功删除
    FAIL 删除失败
*/   
bool CPosixShm::Remove()
{
    return (shm_unlink(m_szIpcName) == 0);
}


/*
功能:分配共享内存块(不存在则创建)
参数:
    int iSize[in] 共享内存块大小 =0的时候表示共享内存已经创建
返回值:
    NULL 申请内存失败
    非NULL 指向共享内存的指针
*/
void* CPosixShm::Alloc(int iSize)
{
    int iRet = -1;
    int iCurSize = 0;
    
    //共享内存不存在 则创建
    if (!Exist())
    {
        if (m_iDebugOn == DEBUG_ON)
        {
            printf("(%s-%d) shm have not been created!\n",FILELINE);
        } 
        if (!Open())
        {
            return NULL;
        }       
        ftruncate(m_iShmId,iSize);
        m_pvShmHead = mmap(NULL,iSize,PROT_READ|PROT_WRITE,MAP_SHARED,m_iShmId,0);
        Close();
    }
    //如果已经存在 则判断大小 不够大则重新创建 够大则RESET内存
    else
    {
        if (m_iDebugOn == DEBUG_ON)
        {
            printf("(%s-%d) shm have been created!\n",FILELINE);
        }       
        iCurSize = Size();
        //空间不足则将空间改为当前设置的大小
        if (iCurSize < iSize)
        {
            if (!Open())
            {
                return false;
            }       
            ftruncate(m_iShmId,iSize);
            m_pvShmHead = mmap(NULL,iSize,PROT_READ|PROT_WRITE,MAP_SHARED,m_iShmId,0);
            Close();
        } 
        else //直接关联共享内存
        {
            if (!Attach())
            {
                return NULL;
            }         
        }
    }
    return m_pvShmHead;
}


/*
功能:关联进程与共享内存块
参数:
返回值:
    SUCC 成功
    其他失败
*/
bool CPosixShm::Attach()
{
    int iRet = -1;
    int iSize = -1;
    
    iSize = Size();
    if (iSize < 0 )
    {
        return false;
    }       
    
    if (!Open())
    {
        return false;
    }   
    m_pvShmHead = mmap(NULL,iSize,PROT_READ|PROT_WRITE,MAP_SHARED,m_iShmId,0);
    Close();
    return true;
}
/*
功能:去掉关联进程与共享内存块
参数:
返回值:
    SUCC 成功
    其他失败
*/
void CPosixShm::Detach()
{
    m_pvShmHead = NULL;
}


/**********************************Posix 共享内存*****************************************************/





#endif



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值