封装ipc,共享内存,消息队列,信号量

IPC 通讯接口封装使用介绍

 

l  IPC 初始化

成功返回对应的结果体指针,失败返回 NULL

1.         初始化消息队列 ipcMsq_p ipc_initialize_msq(key_t key, int msglen )

msglen 表示该消息队列可以接受的单个消息的最大长度

2.         初始化共享内存 ipcShm_p ipc_initialize_shm(key_t key, key_t semkey, enum SHMTYPE type, int size, int elemsize)

参数说明 key -共享内存 key 值; semkey -共享内存使用的信号量 key 值; type -共享内存类型; size -申请的共享内存大小; elemsize -共享内存每个元素大小

3.         初始化数组型共享内存,由于数组需要维数和每维的大小,故需独立的初始化函数

ipcShm_p ipc_initialize_array_shm(key_t key, key_t semkey, int elemsize, int dim, ...)

key -共享内存 key semkey -共享内存使用的信号量 key 值; dim -数组维数;后面是 dim 个整型数分别表示每维大小

4.         初始化信号量 ipcSem_p ipc_initialize_sem(key_t key, int nsems)

Key -信号量 key nsems -该信号量集合的信号量数

l  IPC 操作

统一的接口函数 int ipc_op(ipcComm_p ipc, enum IPCOP op, int semnum, void *buf, ...)

Ipc -对应的 ipc op -操作类型; semnum -信号量集合中的成员号; buf -存储操作数据空间; buf 后的参数因 IPC 类型不同而异,具体参考下面的细节。

1.         读消息队列调用方式 ipc_op(ipc, READ, 0, NULL) ,读取的信息不直接返回给用户,而是作为参数传递给用户自定义的一个函数进行处理,参考 IPC 配置接口。

2.         写消息队列 ipc_op(ipc, WRITE, 0, buf, len) buf 指向需要写入消息队列的数据, len 是需要写入的数据长度。

3.         写消息队列 ipc_op(ipcComm_p ipc, WRITE, 0, void *buf, int buflen, long mtype)

参数说明 :buf 是要放入消息队列的数据, buflen 是该数据区的大小, mtype 用于指定这条消息的类型

4.         读消息队列 ipc_op(ipcComm_p ipc, READ, 0, void *buf, long *mtype)

参数说明: buf 是返回参数,函数执行后将指向从消息队列取到的数据; mtype 既是输入参数又是输出参数,作为输入参数,它指定了要取的消息的类型,作为返回参数,它返回了取到的消息的实际类型,当该值为 0 时,表示取队列中第一条数据;返回值:本次读取消息的实际长度。

5.         读消息队列深度 int msq_get_depth(ipcComm_p ipc)

6.         读写普通型共享内存 ipc_ip(ipc, READ/WRITE, 0, buf, len, off) ,从 off 偏移处读或写 len 长字节

7.         读写堆栈型或循环队列型共享内存 ipc_op(ipc, READ/WRITE, 0, buf)

8.         读写数组型共享内存 ipc_ip(ipc, READ/WRITE, 0, buf, dim1, dim2, …) dim 是各维数组下标

9.         信号量锁操作 ipc_op(ipc, LOCK, semnm, NULL) ,使用第 semnm 信号量上锁。

10.     信号量解锁操作 ipc_op(ipc, LOCK, semnm, NULL) ,解锁第 semnm 信号量。

11.     Ipc_op(ipc, FREE/RMIT, 0, NULL)

释放只能 FREE RMIT 之一, RMIT 释放资源后同时会删除 IPC

l  IPC 配置接口

1.         消息队列

1)         设置函数处理指针 int msq_set_handles(ipcMsq_p msq, comm_fn1 handle_read, comm_fn2 empty, comm_fn2 full)

n  函数原型 typedef void *(*comm_fn1)(void *);  typedef int (*comm_fn2)(void *);

n  Handle_read ――处理从消息队列读取的信息函数指针,如果未定义则读取消息队列函数消息队列中下一条消息或返回 0 ,如果该函数处理返回 NULL 则读取消息队列操作认为出错返回- 1

n  Empty ――读取消息队列操作处理消息队列为空的函数指针,如果未定义则读取消息队列操作返回 -2 ,如果该函数返回- 1 则读取消息队列操作也返回- 1 ,否则返回 0

n  Full ――写取消息队列操作处理消息队列满的函数指针,返回处理同 empty

2)         设置每次读取消息队列消息数 int msq_set_readbatch(ipcMsq_p msq, int batch)

3)         设置读写消息队列时不等待模式 int msq_set_nowait(ipcMsq_p msq)

4)         设置读写消息队列时等待模式 int msq_set_wait(ipcMsq_p msq)

 

l  待解决的地方

1 )将 ipc_op 函数中的参数 semun 作为变长参数;

2 )设法解决变长参数个数判断问题;

3 )是否需要将各种共享内存描述结构体 ipcShm_t 放入共享内存,让其他进程获取。这

个结构体保存了如何组织共享内存的信息。

4 )完善成线程安全

 

#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#include <errno.h>
#include "ipc_comm.h"

void Free(void **ptr)
{
    if(*ptr)
    {
        free(*ptr);
        *ptr = NULL;
    }
}

/*return NULL if error
  *malloc memory for common ipc struct
  */
ipcComm_p ipc_initialize(enum IPCTYPE type)
{
    ipcComm_p name;
   
    name = (ipcComm_p)malloc(sizeof(ipcComm_t));
    if(NULL == name)
    {
        /*error*/
        return NULL;
    }
    memset(name, 0, sizeof(ipcComm_t));
    switch(type)
    {
        case MSQ:
            name->private = malloc(sizeof(ipcMsq_t));
            break;
        case SHM:
            name->private = malloc(sizeof(ipcShm_t));
            break;
        case SEM:
            name->private = malloc(sizeof(ipcSem_t));
            break;
    }
    if(NULL == name->private)
    {
        /*error*/
        Free((void **)(&name));
        return NULL;
    }

    return name;
}

int ipc_free(ipcComm_p ipc)
{
    ipcMsq_p msq;

    if(MSQ == ipc->ipctype)
    {
        msq = (ipcMsq_p)(ipc->private);
        Free((void**)(&(msq->msg)));
    }/*
    if(SHM == ipc->ipctype)
    {
        shm = (ipcShm_p)(ipc->private);
        if(ISARRAYSHM(shm->type))
        {
            Free((void **)(&(shm->array.bounds)));
            Free((void **)(&(shm->array.constants)));
        }
    }*/
    Free((void **)(&(ipc->private)));
    Free((void **)(&ipc));
   
    return 0;
}

/*call this before read or write*/
int ipc_create_msq(ipcComm_p ipc)
{
    int msqid;

    if(NULL == ipc)
    {
        /*error*/
        return -1;
    }   
    if(0 == ipc->key)
    {
        /*IPC_PRIVATE, dangerous*/
        return -1;
    }
    msqid = msgget(ipc->key, IPC_CREAT | IPC_EXCL | ipc->mode);
    if(-1 == msqid)
    {
        /* queue exist already */
        if(EEXIST == errno)
        {
            msqid = msgget(ipc->key, ipc->mode);
            if(-1 == msqid)
            {
                /*error*/
                return -1;
            }
        }
        else{
            /*error*/
            return -1;
        }
    }
    ipc->id = msqid;
   
    return 0;
}

/*initial msq, return NULL if fail else return allocated ipcMsq_p*/
/*ipcMsq_p ipc_initialize_msq(key_t key)*/
ipcMsq_p ipc_initialize_msq(key_t key, int msglen)
{
    ipcMsq_p msq;
    ipcComm_p ipc;
       
    ipc = ipc_initialize(MSQ);
    if(NULL == ipc)
    {
        /*error*/
        return NULL;
    }
    ipc->ipctype = MSQ;
    ipc->key = key;
    ipc->mode = 0666;
   
    memset(ipc->private, 0, sizeof(ipcMsq_p));
    msq = (ipcMsq_p)(ipc->private);
    /*msq->msglen = MAXMSGLEN;*/
    msq->msglen = msglen;    /*mod by lxs*/
    msq->comm = ipc;
    msq->batch = 1;
    msq->mtype = 1;
    msq->nowait = 0;    /*wait if no message*/
    msq->msq_handle_read = NULL;
    msq->msq_empty = NULL;
    msq->msq_full = NULL;
    msq->msg = malloc(msglen + 4);        /*del by lxs*/
    memset(msq->msg, 0, msglen + 4);
    /*if(NULL == msq->msg)
    {
        ipc_free(ipc);
        return NULL;
    }
    memset(msq->msg, 0, sizeof(msqMsg_t));
    msq->msg->mtype = msq->mtype;*/
   
    if(-1 == ipc_create_msq(ipc))
    {
        /*error*/
        ipc_free(ipc);
        return NULL;
    }
   
    return msq;
}

/*set handle functions*/
int msq_set_handles(ipcMsq_p msq, comm_fn1 handle_read, comm_fn2 empty, comm_fn2 full)
{
    if(NULL == msq)
    {
        /*error*/
        return -1;
    }

    msq->msq_empty = empty;
    msq->msq_full = full;
    msq->msq_handle_read = handle_read;
   
    return 0;
}

/*set batch messages each ipc_op*/
int msq_set_readbatch(ipcMsq_p msq, int batch)
{
    if(NULL == msq)
    {
        /*error*/
        return -1;
    }
    if(batch > 0)
    {
        msq->batch = batch;
    }
    /*msq->batch = MAX_MSQDEP;
    msq->batch = msq_get_depth(msq->comm);*/
   
    return 0;   
}

/*read or write return immediatly*/
int msq_set_nowait(ipcMsq_p msq)
{
    if(NULL == msq)
    {
        /*error*/
        return -1;
    }
    msq->nowait |= IPC_NOWAIT;
   
    return 0;   
}

/*wait until read or write finish*/
int msq_set_wait(ipcMsq_p msq)
{
    if(NULL == msq)
    {
        /*error*/
        return -1;
    }
    msq->nowait &= ~IPC_NOWAIT;
   
    return 0;       
}

/*get queue depth*/
int msq_get_depth(ipcComm_p ipc)
{
    struct msqid_ds buf;
   
    if(-1 == msgctl(ipc->id, IPC_STAT, &buf))
    {
        /*error*/
        return -1;
    }

    return buf.msg_qnum;
}

/*read batch msq each time
 *return if no message in queue
 */
int ipc_read_msq(ipcComm_p ipc, void *buf, va_list ap)
{
    int i;
    ipcMsq_p msq;
    int ret = 0;
    int retcode = 0;

    long *mtype;        /*add by lxs, input and output*/
   
    if(NULL == ipc)
    {
        /*error*/
    }
   
    msq = (ipcMsq_p)(ipc->private);

    /*add by lxs*/
    mtype = va_arg(ap, long *);
    /*add by lxs*/
   
    /*tmp->mtext = (char *)malloc(sizeof(char) * (msq->msglen));*/
    i = 0;
    /* using this to avoid read empty msq
    batch = msq_get_depth(ipc);
    (batch <= msq->batch) ? (batch) : (batch = msq->batch);
    while(i < batch)*/
    while(i < msq->batch)
    {
    RETRY:
        memset(msq->msg, 0, sizeof(char) * (msq->msglen + 4));
        ret = msgrcv(ipc->id, msq->msg, msq->msglen, *mtype, msq->nowait);        /*mod by lxs*/
        if(ret == -1)
        {
            /*interrupt by signal*/
            if(EINTR == errno)
            {
                goto RETRY;
            }
            /* no message */
            if(ENOMSG == errno)
            {
                if(msq->msq_empty)
                {
                    if(-1 == msq->msq_empty(NULL))
                    {
                        /*error*/
                        retcode = -1;
                    }
                }else{
                    /*not define empty function*/
                    retcode = -2;
                }
                break;
            }
            else{
                /*queue was delete*/
                if(EIDRM == errno)
                {
                    retcode = -3;
                }else{
                    /*read error*/
                    retcode = -1;
                }
                break;
            }
        }       
        /*add by lxs*/
        *mtype = *(long *)msq->msg;
        memcpy(buf, msq->msg + sizeof(long), ret);
        retcode = ret;
        /*add by lxs*/
        /*if(msq->msq_handle_read)
        {
            if(NULL == msq->msq_handle_read((void*)tmp))
            {
                retcode = -1;
                break;
            }
        }*/
        i++;
    }

    return retcode;
}


int ipc_write_msq(ipcComm_p ipc, void *buf, va_list ap)
{
    ipcMsq_p msq;
    /*msqMsg_p tmp;*/
    int ret = 0;
    int retcode = 0;
    int len;
   
    long mtype;        /*add by lxs*/
   
    if((NULL == ipc) || (NULL == buf))
    {
        /*error*/
        return -1;
    }
    len = va_arg(ap, int);
    mtype = va_arg(ap, long);    /*add by lxs*/
    msq = (ipcMsq_p)(ipc->private);
    if(len > msq->msglen)    /*add by lxs*/
    {
        /*error*/
        return -1;
    }

    /*mod by lxs*/
    memset(msq->msg, 0x00, msq->msglen + sizeof(long));
    *(long *)msq->msg = mtype;
    memcpy(msq->msg + sizeof(long), buf, len);
    /*mod by lxs*/

RETRY:
    /*ret = msgsnd(ipc->id, tmp, MAXMSGLEN, msq->nowait);*/
    ret = msgsnd(ipc->id, msq->msg, len, msq->nowait);    /*mod by lxs, write actual len*/
    if(-1 == ret)
    {
        /*interrupt by signal*/
        if(EINTR == errno)
        {
            goto RETRY;
        }
        if(EAGAIN == errno)
        {
            /*queue is full, clear up queue*/
            if(msq->msq_full)
            {
                if(-1 == msq->msq_full(NULL))
                {
                    /*error*/
                    retcode = -1;
                }
            }else{
                retcode = -2;
            }
        }else{
            /*queue was delete*/
            if(EIDRM == errno)
            {
                retcode = -3;
            }else{
                /*write error*/
                retcode = -1;
            }
        }
    }

    return retcode;
}

int ipc_ctl_msq()
{
    /*TODO...*/
    return 0;
}

int ipc_delete_msq(ipcComm_p ipc)
{
    struct msqid_ds buf;

    if(-1 == msgctl(ipc->id, IPC_RMID, &buf)){
        /*error*/
        return -1;
    }
   
    return 0;
}

int ipc_create_shm(ipcComm_p ipc)
{
    ipcShm_p shm;
    int shmid;
    void *shmOffset;
#ifdef ENABLE_SHMSEM
    int semid;
    union semun sem;
    int ret;
#endif
    int flag = 0;    /*create or not*/

    if(NULL == ipc)
    {
        /*error*/
        return -1;
    }
    if(0 == ipc->key)
    {
        /*IPC_PRIVATE, dangerous*/
        return -1;
    }   
    shm = (ipcShm_p)(ipc->private);
    shmid = shmget(ipc->key, shm->size, IPC_CREAT | IPC_EXCL | ipc->mode);
    if(-1 == shmid)
    {
        if(EEXIST == errno)
        {
            shmid = shmget(ipc->key, 0, 0666);
            if(-1 == shmid)
            {
                /*error*/
                return -1;
            }
            ipc->id = shmid;
            shmOffset = shmat(shmid, 0, 0);
            if((void *)-1 == shmOffset)
            {
                /*error*/
                return -1;
            }
            shm->shmaddr = shmOffset;
        }else{
            /*error*/
            return -1;
        }
    }else{
        flag = 1;
        ipc->id = shmid;
        shmOffset = shmat(ipc->id, 0, 0);
        if((void *)-1 == shmOffset){
            /*error*/
            shmctl(ipc->id, IPC_RMID, NULL);
            return -1;
        }   
        shm->shmaddr = shmOffset;
        memset(shm->shmaddr, 0, shm->size);
    }
   
#ifdef ENABLE_SHMSEM
    /*init sem protect shm*/
    errno = 0;
    shm->mode= 0666;
    semid = semget(ipc->semkey, 1, IPC_CREAT | IPC_EXCL | shm->mode);
    if(-1 == semid){
        if(errno == EEXIST){
            semid = semget(ipc->semkey, 0, 0666);
            if(-1 == semid){
                /*error*/
                if(flag)
                {
                    shmdt(shm->shmaddr);
                    shmctl(ipc->id, IPC_RMID, NULL);
                }
                return -1;
            }
            shm->semid = semid;
        }else{
            /*error*/
            if(flag)
            {
                shmdt(shm->shmaddr);
                shmctl(ipc->id, IPC_RMID, NULL);
            }
            return -1;
        }
    }else{
        shm->semid = semid;
        sem.val = 1;
        ret = semctl(shm->semid, 0, SETVAL, sem);
        if(ret == -1){
            /*error*/
            ipc_delete_shm(ipc);
            return -1;
        }
    }
#endif

    return 0;
}

/*initial shm, return NULL if fail else return allocated ipcShm_p*/
ipcShm_p ipc_initialize_shm(key_t key, key_t semkey, enum SHMTYPE type, int size, int elemsize)
{
    ipcShm_p shm;
    ipcComm_p ipc;
   
    ipc = ipc_initialize(SHM);
    if(NULL == ipc)
    {
        /*error*/
        return NULL;
    }
    ipc->ipctype = SHM;
    ipc->key = key;
    #ifdef ENABLE_SHMSEM
    ipc->semkey = semkey;
    #endif
    ipc->mode = 0666;
   
    memset(ipc->private, 0, sizeof(ipcShm_p));
    shm = (ipcShm_p)(ipc->private);
    shm->comm = ipc;
    shm->size = size;
    shm->elemsize = elemsize;
    switch(type)
    {
        case ORDINARY:
            SETORDINARYSHM(shm->type);
            break;
        case ARRAY:
            SETARRAYSHM(shm->type);
            break;
        case STACK:
            SETSTACKYSHM(shm->type);
            shm->stack.top = 0;
            shm->stack.depth = size / elemsize;
            shm->size = size + 4;    /*first 4bytes is top*/
            break;
        case ROUNDQ:
            SETROUNDQSHM(shm->type);
            shm->roundq.front = 0;
            shm->roundq.rear = 0;
            shm->roundq.depth = size / elemsize + 1;    /*a addition elem for distinguish full queue and empty queue*/
            shm->size = size + elemsize + 8;    /*first 8bytes is front and rear*/
            break;
        default:
            /*unknow shm type*/
            return NULL;
    }

    if(-1 == ipc_create_shm(ipc))
    {
        /*error*/
        ipc_free(ipc);
        return NULL;
    }
   
    return shm;
}

#ifdef ENABLE_SHMSEM
int shmsemlock(int semid)
{
    struct sembuf sbuf;
    int ret;
   
    memset(&sbuf, 0, sizeof(struct sembuf));
    sbuf.sem_num = 0;
    sbuf.sem_op = -1;
    sbuf.sem_flg = SEM_UNDO;
retry_lock:
    ret = semop(semid, &sbuf, 1);
    if(-1 == ret){
        if(EINTR == errno){
            goto retry_lock;
        }
        /*error*/
        return -1;
    }
   
    return 0;
}

int shmsemunlock(int semid)
{
    struct sembuf sbuf;
    int ret;
   
    sbuf.sem_num = 0;
    sbuf.sem_op = 1;
    sbuf.sem_flg = SEM_UNDO;
retry_unlock:
    ret = semop(semid, &sbuf, 1);
    if(-1 == ret){
        if(EINTR == errno){
            goto retry_unlock;
        }
        /*error*/
        return -1;
    }
}
#endif

/*off is relative offset*/
static int ipc_read_ordinary_shm(ipcComm_p ipc, void *buf, int len, int off)
{
    ipcShm_p shm;
   
    if((NULL == ipc) || (NULL == buf))
    {
        /*error*/
        return -1;
    }
    shm = (ipcShm_p)(ipc->private);   
    /*len = va_arg(ap, int);
    off = va_arg(ap, int);*/
    if(off + len > shm->size)
    {
        /*error*/
        return -1;
    }

#ifdef ENABLE_SHMSEM
    /*lock*//*
    if(READLOCK(shm->type))
    {*/
        if(0 != shmsemlock(shm->semid))
        {
            /*error*/
            return -1;
        }
    /*}*/
#endif

    memmove((char *)(buf), (char *)(shm->shmaddr) + off, len);
   
#ifdef ENABLE_SHMSEM
    /*unlock*//*
    if(READLOCK(shm->type))
    {*/
        if(0 != shmsemunlock(shm->semid))
        {
            /*error*/
            return -1;
        }
    /*}*/
#endif

    return 0;
}

static int ipc_write_ordinary_shm(ipcComm_p ipc, void *buf, int len, int off)
{
    ipcShm_p shm;
       
    if((NULL == ipc) || (NULL == buf))
    {
        /*error*/
        return -1;
    }
    shm = (ipcShm_p)(ipc->private);   
    /*len = va_arg(ap, int);
    off = va_arg(ap, int);*/
    if(off + len > shm->size)
    {
        /*error*/
    }
#ifdef ENABLE_SHMSEM
    /*lock*/
    /*if(WRITELOCK(shm->type))
    {*/
        if(0 != shmsemlock(shm->semid))
        {
            /*error*/
            return -1;
        }
    /*}*/
#endif

    memmove((char *)(shm->shmaddr) + off, (char *)buf, len);
   
#ifdef ENABLE_SHMSEM
    /*lock*//*
    if(WRITELOCK(shm->type))
    {*/
        if(0 != shmsemunlock(shm->semid))
        {
            /*error*/
            return -1;
        }
    /*}*/
#endif
    return 0;
}

#ifdef ENABLE_ARRAYSHM
int ipc_locate_array_shm(ipcShm_p shm, va_list ap, int *off)
{
    int ind;
    int i;

    *off = 0;
    for(i = 0; i < shm->array.dim; i++)
    {
        ind = va_arg(ap, int);
        if((ind <=0) || (ind > shm->array.bounds[i]))
        {
            /*error, overflow*/
            return -1;
        }
        *off = *off + ind * shm->array.constants[i];
    }
}

/*initial array shm, return NULL if fail else return allocated ipcShm_p*/
ipcShm_p ipc_initialize_array_shm(key_t key, key_t semkey, int elemsize, int dim, ...)
{
    va_list ap;
    ipcShm_p shm;
    int i;
    int ind;
    int *bounds;
    int *constants;
    int size = 1;;
   
    bounds = (int *)malloc(sizeof(int) * dim);
    if(NULL == bounds)
    {
        /*error*/
        return NULL;
    }
    memset(bounds, 0, sizeof(int) * dim);
    i = 0;
    va_start(ap, dim);
    while(i < dim)
    {
        ind = va_arg(ap, int);
        if(ind <= 0)
        {
            /*error*/
            Free((void **)(&bounds));
            return NULL;
        }
        bounds[i] = ind;
        size *= ind;
        i++;
    }
    constants = (int *)malloc(sizeof(int) * dim);
    if(NULL == constants)
    {
        /*error*/
        Free((void **)(&bounds));
        return NULL;
    }
    memset(constants, 0, sizeof(int) * dim);
    constants[dim - 1] = 1;
    i = dim - 2;
    while(i >= 0)
    {
        constants[i] = bounds[i + 1] * constants[i + 1];
        i--;
    }

    shm = ipc_initialize_shm(key, semkey, ARRAY, size * elemsize, elemsize);
    if(NULL == shm)
    {
        /*error*/
        Free((void **)(&bounds));
        Free((void **)(&constants));
        ipc_free(shm->comm);
        return NULL;
    }
    shm->array.dim = dim;
    shm->array.bounds = bounds;
    shm->array.constants = constants;

    return shm;
}

/*
ipcShm_p ipc_initialize_array_shm(key_t key, key_t semkey, int size, int elemsize, int dim, ...)
{
    va_list ap;
    ipcShm_p shm;
    int i;
    int ind;
   
    shm = ipc_initialize_shm(key, semkey, ARRAY, size, elemsize);
    if(NULL == shm)
    {
        return NULL;
    }
    shm->array.dim = dim;
    shm->array.bounds = (int *)malloc(sizeof(int) * dim);
    if(NULL == shm->array.bounds)
    {
        ipc_free(shm->comm);
        return NULL;
    }
    memset(shm->array.bounds, 0, sizeof(int) * dim);
    i = 0;
    va_start(ap, dim);
    while(i < dim)
    {
        ind = va_arg(ap, int);
        if(ind <= 0)
        {
            Free((void **)(&(shm->array.bounds)));
            ipc_free(shm->comm);
            return NULL;
        }
        shm->array.bounds[i] = ind;
        i++;
    }
    shm->array.constants = (int *)malloc(sizeof(int) * dim);
    if(NULL == shm->array.constants)
    {
        Free((void **)(&(shm->array.bounds)));
        ipc_free(shm->comm);
        return NULL;
    }
    memset(shm->array.constants, 0, sizeof(int) * dim);
    shm->array.constants[dim - 1] = 1;
    i = dim - 2;
    while(i >= 0)
    {
        shm->array.constants[i] = shm->array.bounds[i] * shm->array.bounds[i + 1];
        i--;
    }
   
    return shm;
}*/

int ipc_read_array_shm(ipcComm_p ipc, void *buf, va_list ap)
{
    int off;
    ipcShm_p shm;
   
    if((NULL == ipc) || (NULL == buf))
    {
        /*error*/
        return -1;
    }
    shm = (ipcShm_p)(ipc->private);   
    if(-1 == ipc_locate_array_shm(shm, ap, &off))
    {
        /*error*/
        return -1;
    }
    off = off * shm->elemsize;
    if(-1 == ipc_read_ordinary_shm(ipc, buf, shm->elemsize, off))
    {
        /*error*/
        return -1;
    }
   
    return 0;
}

int ipc_write_array_shm(ipcComm_p ipc, void *buf, va_list ap)
{
    int off;
    ipcShm_p shm;
   
    if((NULL == ipc) || (NULL == buf))
    {
        /*error*/
        return -1;
    }
    shm = (ipcShm_p)(ipc->private);   
    if(-1 == ipc_locate_array_shm(shm, ap, &off))
    {
        /*error*/
        return -1;
    }
    off = off * shm->elemsize;
    if(-1 == ipc_write_ordinary_shm(ipc, buf, shm->elemsize, off))
    {
        /*error*/
        return -1;
    }
   
    return 0;
}

int ipc_free_array_shm(ipcComm_p ipc)
{
    ipcShm_p shm;
   
    if(NULL == ipc)
    {
        /*error*/
        return -1;
    }
    shm = (ipcShm_p)(ipc->private);   
    if(ISARRAYSHM(shm->type))
    {
        Free((void **)(&(shm->array.bounds)));
        Free((void **)(&(shm->array.constants)));
    }
/*
    Free((void **)(&(shm->array.bounds)));
    Free((void **)(&(shm->array.constants)));
*/
    return 0;
}
#endif

#ifdef ENABLE_STACKSHM
/*-2/stack is empty, -1/error, 0/suc*/
int ipc_stack_pop_shm(ipcComm_p ipc, void *buf)
{
    int off;
    ipcShm_p shm;
    int retcode = 0;
   
    if((NULL == ipc) || (NULL == buf))
    {
        /*error*/
        return -1;
    }
    shm = (ipcShm_p)(ipc->private);
#ifdef ENABLE_SHMSEM
    /*lock*/
    if(READLOCK(shm->type))
    {
        if(0 != shmsemlock(shm->semid))
        {
            /*error*/
            return -1;
        }
    }
#endif
    /*memmove((char *)(top), (char *)(shm->shmaddr), 4);
    shm->stack.top = atoi(top);*/
    shm->stack.top = *((int *)(shm->shmaddr));
    if(0 == shm->stack.top)
    {
        /*error*/
        retcode = -2;
        goto out;
    }
    off = (shm->stack.top - 1) * (shm->elemsize) + 4;
    memmove((char *)(buf), (char *)(shm->shmaddr) + off, shm->elemsize);
    /*sprintf(top, "%d", --shm->stack.top);
    memmove((char *)(shm->shmaddr), top, 4);*/
    *((int *)(shm->shmaddr)) = --(shm->stack.top);
out:
#ifdef ENABLE_SHMSEM
    /*unlock*/
    if(READLOCK(shm->type))
    {
        if(0 != shmsemunlock(shm->semid))
        {
            /*error*/
            return -1;
        }
    }
#endif
   
    return retcode;
}

/*-2/stack is full, -1/error, 0/suc*/
int ipc_stack_push_shm(ipcComm_p ipc, void *buf)
{
    int off;
    ipcShm_p shm;
    char top[5] = {'/0'};
    int retcode = 0;
   
    if((NULL == ipc) || (NULL == buf))
    {
        /*error*/
        return -1;
    }
    shm = (ipcShm_p)(ipc->private);
#ifdef ENABLE_SHMSEM
    /*lock*/
    if(READLOCK(shm->type))
    {
        if(0 != shmsemlock(shm->semid))
        {
            /*error*/
            return -1;
        }
    }
#endif
    /*memmove((char *)(top), (char *)(shm->shmaddr), 4);
    shm->stack.top = atoi(top);*/
    shm->stack.top = *((int *)(shm->shmaddr));
    if(shm->stack.depth <= shm->stack.top)
    {
        /*error*/
        retcode = -2;
        goto out;
    }
    off = (shm->stack.top) * (shm->elemsize) + 4;
    memmove((char *)(shm->shmaddr) + off, (char *)(buf), shm->elemsize);
    /*sprintf(top, "%d", ++shm->stack.top);
    memmove((char *)(shm->shmaddr), top, 4);*/
    *((int *)(shm->shmaddr)) = ++(shm->stack.top);
   
out:
#ifdef ENABLE_SHMSEM
    /*unlock*/
    if(READLOCK(shm->type))
    {
        if(0 != shmsemunlock(shm->semid))
        {
            /*error*/
            return -1;
        }
    }
#endif
   
    return retcode;
}

/*return top, -1/error*/
int shm_stack_get_top(ipcComm_p ipc)
{
    ipcShm_p shm;
    int top;
   
    if((NULL == ipc) || (NULL == buf))
    {
        /*error*/
        return -1;
    }
    shm = (ipcShm_p)(ipc->private);
#ifdef ENABLE_SHMSEM
    /*lock*/
    if(READLOCK(shm->type))
    {
        if(0 != shmsemlock(shm->semid))
        {
            /*error*/
            return -1;
        }
    }
#endif
    top = *((int *)(shm->shmaddr));
    /*memmove((char *)(top), (char *)(shm->shmaddr), 4);*/
out:
#ifdef ENABLE_SHMSEM
    /*unlock*/
    if(READLOCK(shm->type))
    {
        if(0 != shmsemunlock(shm->semid))
        {
            /*error*/
            return -1;
        }
    }
#endif
   
    return top;
}

/*emptyfull = 0 set stack empty, else set stack full;-1/fail, 0/suc*/
int shm_stack_set_emptyfull(ipcComm_p ipc, int emptyfull)
{
    ipcShm_p shm;
   
    if((NULL == ipc) || (NULL == buf))
    {
        /*error*/
        return -1;
    }
    shm = (ipcShm_p)(ipc->private);
#ifdef ENABLE_SHMSEM
    /*lock*/
    if(READLOCK(shm->type))
    {
        if(0 != shmsemlock(shm->semid))
        {
            /*error*/
            return -1;
        }
    }
#endif
    if(0 == emptyfull)
    {
        *((int *)(shm->shmaddr)) = 0;
    }else{
        *((int *)(shm->shmaddr)) = shm->stack.depth;
    }
    /*memmove((char *)(shm->shmaddr), top, 4);*/
out:
#ifdef ENABLE_SHMSEM
    /*unlock*/
    if(READLOCK(shm->type))
    {
        if(0 != shmsemunlock(shm->semid))
        {
            /*error*/
            return -1;
        }
    }
#endif
   
    return 0;
}

#endif

#ifdef ENABLE_ROUNDQSHM
/*use depth-1 elems to distinguish full queue and empty queue*/
int ipc_deroundq_shm(ipcComm_p ipc, void *buf)
{
    int off;
    ipcShm_p shm;
    /*char front[5] = {'/0'};
    char rear[5] = {'/0'};*/
    int retcode = 0;
   
    if((NULL == ipc) || (NULL == buf))
    {
        /*error*/
        return -1;
    }
    shm = (ipcShm_p)(ipc->private);
#ifdef ENABLE_SHMSEM
    /*lock*/
    if(WRITELOCK(shm->type))
    {
        if(0 != shmsemlock(shm->semid))
        {
            /*error*/
            return -1;
        }
    }
#endif   
    /*memmove((char *)(front), (char *)(shm->shmaddr), 4);
    memmove((char *)(rear), (char *)(shm->shmaddr) + 4, 4);
    shm->roundq.front = atoi(front);
    shm->roundq.rear = atoi(rear);*/
    shm->roundq.front = *((int *)(shm->shmaddr));
    shm->roundq.rear = *((int *)(shm->shmaddr + 4));

    if(shm->roundq.front == shm->roundq.rear)    /*check queue is empty?*/
    {
        /*error, queue if empty*/
        retcode = -2;
        goto out;
    }
    off = (shm->roundq.front) * (shm->elemsize) + 8;
    memmove((char *)(buf), (char *)(shm->shmaddr) + off, shm->elemsize);
    shm->roundq.front = (shm->roundq.front + 1) % (shm->roundq.depth);
    /*sprintf(front, "%d", shm->roundq.front);
    memmove((char *)(shm->shmaddr), (char *)front, 4);*/
    *((int *)(shm->shmaddr)) = shm->roundq.front;

out:
#ifdef ENABLE_SHMSEM
    /*lock*/
    if(WRITELOCK(shm->type))
    {
        if(0 != shmsemunlock(shm->semid))
        {
            /*error*/
            return -1;
        }
    }
#endif

    return retcode;
}

/*use depth-1 elems to distinguish full queue and empty queue*/
int ipc_enroundq_shm(ipcComm_p ipc, void *buf)
{
    int off;
    ipcShm_p shm;
    /*char front[5] = {'/0'};
    char rear[5] = {'/0'};*/
    int retcode = 0;
   
    if((NULL == ipc) || (NULL == buf))
    {
        /*error*/
        return -1;
    }
    shm = (ipcShm_p)(ipc->private);
#ifdef ENABLE_SHMSEM
    /*lock*/
    if(WRITELOCK(shm->type))
    {
        if(0 != shmsemlock(shm->semid))
        {
            /*error*/
            return -1;
        }
    }
#endif
    /*memmove((char *)(front), (char *)(shm->shmaddr), 4);
    memmove((char *)(rear), (char *)(shm->shmaddr) + 4, 4);
    shm->roundq.front = atoi(front);
    shm->roundq.rear = atoi(rear);*/
    shm->roundq.front = *((int *)(shm->shmaddr));
    shm->roundq.rear = *((int *)(shm->shmaddr + 4));

    if(((shm->roundq.rear + 1) % shm->roundq.depth) == (shm->roundq.front))
    {
        /*error, queue if full*/
        retcode = -2;
        goto out;
    }
    off = (shm->roundq.rear) * (shm->elemsize) + 8;
    memmove((char *)(shm->shmaddr) + off, (char *)(buf), shm->elemsize);
    shm->roundq.rear = (shm->roundq.rear + 1) % (shm->roundq.depth);
    /*sprintf(rear, "%d", shm->roundq.rear);
    memmove((char *)(shm->shmaddr) + 4, (char *)rear, 4);*/
    *((int *)(shm->shmaddr + 4)) = shm->roundq.rear;

out:
#ifdef ENABLE_SHMSEM
    /*lock*/
    if(WRITELOCK(shm->type))
    {
        if(0 != shmsemunlock(shm->semid))
        {
            /*error*/
            return -1;
        }
    }
#endif

    return retcode;
}

/*frontrear=0 to get front, else rear; return -1 at error*/
int shm_deroundq_get_front(ipcComm_p ipc, int frontrear)
{
    int pos;
    ipcShm_p shm;
   
    if((NULL == ipc) || (NULL == buf))
    {
        /*error*/
        return -1;
    }
    shm = (ipcShm_p)(ipc->private);
#ifdef ENABLE_SHMSEM
    /*lock*/
    if(WRITELOCK(shm->type))
    {
        if(0 != shmsemlock(shm->semid))
        {
            /*error*/
            return -1;
        }
    }
#endif   
    if(0 == frontrear)
    {
        pos = *((int *)(shm->shmaddr));
    }else{
        pos = *((int *)(shm->shmaddr + 4));
    }

#ifdef ENABLE_SHMSEM
    /*lock*/
    if(WRITELOCK(shm->type))
    {
        if(0 != shmsemunlock(shm->semid))
        {
            /*error*/
            return -1;
        }
    }
#endif

    return pos;
}


/*emptyfull=0 to set empty round queue, else full; return -1 at error*/
int shm_deroundq_set_emptyfull(ipcComm_p ipc, int emptyfull)
{
    int pos;
    ipcShm_p shm;
   
    if((NULL == ipc) || (NULL == buf))
    {
        /*error*/
        return -1;
    }
    shm = (ipcShm_p)(ipc->private);
#ifdef ENABLE_SHMSEM
    /*lock*/
    if(WRITELOCK(shm->type))
    {
        if(0 != shmsemlock(shm->semid))
        {
            /*error*/
            return -1;
        }
    }
#endif   
    if(0 == emptyfull)
    {
        /*front = rear = 0, set queue empty*/
        *((int *)(shm->shmaddr)) = 0;
        *((int *)(shm->shmaddr + 4)) = 0;
    }else{
        /*front = 1, rear = 0, set queue full*/
        *((int *)(shm->shmaddr)) = 1;
        *((int *)(shm->shmaddr + 4)) = 0;
    }

#ifdef ENABLE_SHMSEM
    /*lock*/
    if(WRITELOCK(shm->type))
    {
        if(0 != shmsemunlock(shm->semid))
        {
            /*error*/
            return -1;
        }
    }
#endif

    return pos;
}

#endif

int ipc_read_shm(ipcComm_p ipc, void *buf, va_list ap)
{
    ipcShm_p shm;
    int len;
    int off;
   
    if(NULL == ipc)
    {
        /*error*/
        return -1;
    }
    shm = (ipcShm_p)(ipc->private);
    if(ISORDINARYSHM(shm->type))
    {
        len = va_arg(ap, int);
        off = va_arg(ap, int);
        return ipc_read_ordinary_shm(ipc, buf, len, off);
    }
#ifdef ENABLE_ARRAYSHM
    if(ISARRAYSHM(shm->type))
    {
        return ipc_read_array_shm(ipc, buf, ap);
    }
#endif
#ifdef ENABLE_STACKSHM
    if(ISSTACKYSHM(shm->type))
    {
        return ipc_stack_pop_shm(ipc, buf);
    }
#endif
#ifdef ENABLE_ROUNDQSHM
    if(ISROUNDQSHM(shm->type))
    {
        return ipc_deroundq_shm(ipc, buf);
    }
#endif

    /*not support type*/
    return -1;
}

int ipc_write_shm(ipcComm_p ipc, void *buf, va_list ap)
{
    ipcShm_p shm;
    int len;
    int off;
   
    if(NULL == ipc)
    {
        /*error*/
        return -1;
    }
    shm = (ipcShm_p)(ipc->private);   
    if(ISORDINARYSHM(shm->type))
    {
        len = va_arg(ap, int);
        off = va_arg(ap, int);
        return ipc_write_ordinary_shm(ipc, buf, len, off);
    }
#ifdef ENABLE_ARRAYSHM
    if(ISARRAYSHM(shm->type))
    {
        return ipc_write_array_shm(ipc, buf, ap);
    }
#endif
#ifdef ENABLE_STACKSHM
    if(ISSTACKYSHM(shm->type))
    {
        return ipc_stack_push_shm(ipc, buf);
    }
#endif
#ifdef ENABLE_ROUNDQSHM
    if(ISROUNDQSHM(shm->type))
    {
        return ipc_enroundq_shm(ipc, buf);
    }
#endif
    /*not support type*/
    return -1;
}

int ipc_delete_shm(ipcComm_p ipc)
{
    ipcShm_p shm;
   
    if(NULL == ipc)
    {
        /*error*/
        return -1;
    }
    shm = (ipcShm_p)(ipc->private);
    if(-1 == shmdt(shm->shmaddr)){
        /*error*/
        return -1;
    }
#ifdef ENABLE_SHMSEM
    if(-1 == semctl(shm->semid, 0, IPC_RMID)){
        /*error*/
        return -1;
    }
#endif
    if(-1 == shmctl(ipc->id, IPC_RMID, NULL)){
        /*error*/
        return -1;
    }

    return 0;
}

int ipc_delete_sem(ipcComm_p ipc)
{
    /*union semun sem;
    int i;
   
    i = 0;
    while(i < ipc->sem.nsems)
    {
        ret = semctl(ipc->id, i, IPC_RMID, sem);
        if(ret == -1){           
            return -1;
        }
        i++;
    }*/
    ipcSem_p sem;
    int ret;
   
    if(NULL == ipc)
    {
        /*error*/
        return -1;
    }
    sem = (ipcSem_p)(ipc->private);   
retry_rmid:
    ret = semctl(ipc->id, sem->nsems, IPC_RMID, 0);
    if(ret == -1)
    {
        if(EINTR == errno)
        {
            goto retry_rmid;
        }
        /*error*/
        return -1;
    }
   
    return 0;
}

int ipc_create_sem(ipcComm_p ipc)
{
    int semid;
    union semun arg;
    int ret;
    int i;
    ipcSem_p sem;
   
    if(NULL == ipc)
    {
        /*error*/
        return -1;
    }
    if(0 == ipc->key)
    {
        /*IPC_PRIVATE, dangerous*/
        return -1;
    }   
    sem = (ipcSem_p)(ipc->private);   
    /*init sem protect shm*/
    semid = semget(ipc->key, sem->nsems, IPC_CREAT | IPC_EXCL | 0666);
    if(-1 == semid)
    {
        if(errno == EEXIST)
        {
            semid = semget(ipc->key, 0, 0666);
            if(-1 == semid)
            {
                /*error*/
                return -1;
            }
            ipc->id = semid;
        }else{
            /*error*/
            return -1;
        }
    }else{
        ipc->id = semid;
        i=0;
        arg.val = 1;
        while(i < sem->nsems)
        {
            ret = semctl(ipc->id, i, SETVAL, arg);
            if(ret == -1){
                /*error*/
                ipc_delete_sem(ipc); /*create suc, but init fail, so delete it*/
                return -1;
            }
            i++;
        }
    }
   
    return 0;
}

/*initial sem, return NULL if fail else return allocated ipcSem_p*/
ipcSem_p ipc_initialize_sem(key_t key, int nsems)
{
    ipcSem_p sem;
    ipcComm_p ipc;
   
    ipc = ipc_initialize(SEM);
    if(NULL == ipc)
    {
        /*error*/
        return NULL;
    }
    ipc->ipctype = SEM;
    ipc->key = key;
    ipc->mode = 0666;
   
    memset(ipc->private, 0, sizeof(ipcSem_p));
    sem = (ipcSem_p)(ipc->private);
    sem->comm = ipc;
    sem->nsems = nsems;
    if(-1 == ipc_create_sem(ipc))
    {
        /*error*/
        ipc_free(ipc);
        return NULL;
    }
   
    return sem;
}

int ipc_lock_sem(ipcComm_p ipc, int semnum)
{
    ipcSem_p sem;
    struct sembuf sbuf;
    int ret;
   
    if(NULL == ipc)
    {
        /*error*/
        return -1;
    }
    sem = (ipcSem_p)(ipc->private);
    if((semnum < 0) || (semnum >= sem->nsems))
    {
        /*error*/
        return -1;
    }
    memset(&sbuf, 0, sizeof(struct sembuf));
    sbuf.sem_num = semnum;
    sbuf.sem_op = -1;
    sbuf.sem_flg = SEM_UNDO;
retry_lock:
    ret = semop(ipc->id, &sbuf, 1);
    if(-1 == ret){
        if(EINTR == errno){
            goto retry_lock;
        }
        /*error*/
        return -1;
    }

    return 0;
}

int ipc_unlock_sem(ipcComm_p ipc, int semnum)
{
    ipcSem_p sem;
    struct sembuf sbuf;
    int ret;
   
    if(NULL == ipc)
    {
        /*error*/
        return -1;
    }
    sem = (ipcSem_p)(ipc->private);
    if((semnum < 0) || (semnum >= sem->nsems))
    {
        /*error*/
        return -1;
    }
    memset(&sbuf, 0, sizeof(struct sembuf));
    sbuf.sem_num = semnum;
    sbuf.sem_op = 1;
    sbuf.sem_flg = SEM_UNDO;
retry_unlock:
    ret = semop(ipc->id, &sbuf, 1);
    if(-1 == ret){
        if(EINTR == errno){
            goto retry_unlock;
        }
        /*error*/
        return -1;
    }

    return 0;
}

int ipc_ctl_sem()
{
    /*TODO...*/
    return 0;
}

/*
  * free malloc space and ipcs also
  * call neither this or ipc_free at last
  */
int ipc_rmit(ipcComm_p ipc)
{   
    switch(ipc->ipctype)
    {
        case MSQ:
            ipc_delete_msq(ipc);
            break;
        case SHM:
            ipc_delete_shm(ipc);
            break;
        case SEM:
            ipc_delete_sem(ipc);
            break;
        default:
            /*unknow ipctype*/
            break;
    }
    ipc_free(ipc);
   
    return 0;
}

/*
 *call like ipc_op(ipc, READ, 0, NULL, mtype) to read msq by mtype;
 *call like ipc_op(ipc, WRITE, 0, buf, len, mtype) to write buf to msq;
 *set buf=NULL whem lock or unlock the semnum sem, call like ipc_op(ipc, op, semnum, NULL);
 *read shm to buf, or write buf to shm,
 *call like ipc_op(ipc, op, 0, buf, len, off) when ordinary shm ops;
 *call like ipc_op(ipc, op, 0, buf, dim1, dim2, dim3, ...) when array shm ops, dims are array 下标;
 *call like ipc_op(ipc, op, 0, buf) when stack or roundq shm ops.
 */
int ipc_op(ipcComm_p ipc, enum IPCOP op, int semnum, void *buf, ...)
{
    va_list ap;
   
    ipc->op = op;
    switch(ipc->ipctype)
    {
        case MSQ:
            switch(op)
            {
                case CREATE:
                    return ipc_create_msq(ipc);
                case READ:
                    va_start(ap, buf);
                    return ipc_read_msq(ipc, buf, ap);
                case WRITE:
                    va_start(ap, buf);
                    return ipc_write_msq(ipc, buf, ap);
                case DEPTH:
                    return msq_get_depth(ipc);
                case FREE:
                    return ipc_free(ipc);
                case RMIT:
                    return ipc_rmit(ipc);
                default:
                    /*unsupport op*/
                    return -1;
            }
            break;
        case SHM:
            va_start(ap, buf);
            switch(op)
            {
                case CREATE:
                    return ipc_create_shm(ipc);
                case READ:
                    return ipc_read_shm(ipc, buf, ap);
                case WRITE:
                    return ipc_write_shm(ipc, buf, ap);
                case FREE:
                #ifdef ENABLE_ARRAYSHM
                    ipc_free_array_shm(ipc);
                #endif
                    return ipc_free(ipc);
                case RMIT:
                    return ipc_rmit(ipc);
                default:
                    /*unsurpport op*/
                    return -1;
            }
            break;
        case SEM:
            switch(op)
            {
                case CREATE:
                    return ipc_create_sem(ipc);
                case LOCK:
                    return ipc_lock_sem(ipc, semnum);
                case UNLOCK:
                    return ipc_unlock_sem(ipc, semnum);
                case FREE:
                    return ipc_free(ipc);
                case RMIT:
                    return ipc_rmit(ipc);
                default:
                    /*unsupport op*/
                    return -1;
            }
            break;
        default:
            /*unsupport ipctype*/
            return -1;
    }
   
    return 0;
}

 

#ifndef __IPC_CONN_H
#define __IPC_CONN_H

#include <sys/types.h>

/*#define MAXMSGLEN 1024
typedef struct msqMsg_s{
    long int mtype;
    char mtext[MAXMSGLEN];
}msqMsg_t, *msqMsg_p;*/

typedef int (*comm_fn)(void *, void *);
typedef void *(*comm_fn1)(void *);
typedef int (*comm_fn2)(void *);
typedef int (*comm_fn3)(int);

enum IPCTYPE{
    MSQ = 1,
    SHM,
    SEM,
};

enum IPCOP{
    INIT = 1,
    CREATE,
    READ,
    WRITE,
    DEPTH,
    LOCK,
    UNLOCK,
    FREE,    /*free struct ipc*/
    RMIT,    /*rmit ipc, and free struct ipc*/
};


#define MAX_MSQDEP (~(1 << 31))    /*0x7FFFFFFF*/
#define DECLARE_ARRAYSHM

typedef struct ipcComm_s{
    enum IPCTYPE ipctype;    /*msq, shm, sem*/
    enum IPCOP op;        /*create , read , write, lock , unlock*/
   
    key_t key;
    #ifdef ENABLE_SHMSEM
    int semkey;    /*for write shm*/
    #endif
    int id;
   
    int status;
    int mode;    /**/
   
    /*msq, shm, sem private date
     *after initilize, it point to ipcMsq_p or ipcShm_p or ipcSem_p
     */
    void * private;
   
    #if ENABLE_STATISTIC
    /*statistic interface*/
    #endif
   
    #if ENABLE_MONITOR
    /*monitor interface*/
    #endif
}ipcComm_t, *ipcComm_p;

typedef struct ipcMsq_s{
    ipcComm_p comm;    /*point back*/
    int batch;    /*read messages once*/
    int msglen;
    int nowait;
    comm_fn1 msq_handle_read;    /*handle messages*/
    comm_fn2 msq_empty;    /*read empty queue*/
    comm_fn2 msq_full;    /*write full queue*/
    long int mtype;
    void *msg;
}ipcMsq_t, *ipcMsq_p;

enum SHMTYPE{
    ORDINARY,
    ARRAY,
    STACK,
    ROUNDQ,   
};

union semun{
    int val;
    struct semid_ds *buf;
    ushort *array;
};

#define ISORDINARYSHM(type) ((type) & 0x100)
#define ISARRAYSHM(type) ((type) & 0x200)
#define ISSTACKYSHM(type) ((type) & 0x400)
#define ISROUNDQSHM(type) ((type) & 0x800)
#define SETORDINARYSHM(type) ((type) |= 0x100)
#define SETARRAYSHM(type) ((type) |= 0x200)
#define SETSTACKYSHM(type) ((type) |= 0x400)
#define SETROUNDQSHM(type) ((type) |= 0x800)

typedef struct ipcShm_s{
    ipcComm_p comm;    /*point back*/
    int size;
    int elemsize;
    void *shmaddr;
   
    /*bit0 read lock
     *bit1 write lock
     *bit8 ordinary shm
     *bit9 array shm
     *bit10 stack shm
     *bit11 round queue shm
     *bit12 ...
     */
    int type;
   
    union{
        struct{
            int dim;    /*array dimension*/
            int *bounds;    /*array dimension bound*/
            int *constants;    /**/
        }array;
        struct{
            int top;    /*stack top*/
            int depth;    /*max elems*/
        }stack;
        struct{        /*use depth - 1 elems*/
            int front;    /*dequeue*/
            int rear;    /*enqueue*/
            int depth;
        }roundq;
    };
    #ifdef ENABLE_SHMSEM
    int semid;
    int mode;/*
    #define READLOCK(x) ((x) & 0x1)
    #define WRITELOCK(x) ((x) & 0x2)*/
    #endif
}ipcShm_t, *ipcShm_p;

typedef struct ipcSem_s{
    ipcComm_p comm;    /*point back*/
    int nsems;
}ipcSem_t, *ipcSem_p;

extern int ipc_op(ipcComm_p ipc, enum IPCOP op, int semnum, void *buf, ...);
/*extern ipcMsq_p ipc_initialize_msq(key_t key);*/
extern ipcMsq_p ipc_initialize_msq(key_t key, int msglen);    /*mod by lxs*/
extern int msq_set_readbatch(ipcMsq_p msq, int batch);
extern int msq_set_handles(ipcMsq_p msq, comm_fn1 handle_read, comm_fn2 empty, comm_fn2 full);
extern int msq_set_wait(ipcMsq_p msq);
extern int msq_set_nowait(ipcMsq_p msq);
extern ipcComm_p ipc_initialize(enum IPCTYPE type);
extern ipcShm_p ipc_initialize_shm(key_t key, key_t semkey, enum SHMTYPE type, int size, int elemsize);
extern ipcShm_p ipc_initialize_array_shm(key_t key, key_t semkey, int elemsize, int dim, ...);
extern ipcSem_p ipc_initialize_sem(key_t key, int nsems);

#endif

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值