//
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream.h>
#include <errno.h>
#include <fstream.h>
// sem 信号量机制
#include "hipc.h"
#include "rw.h"
static int semtran(key_t key);
static int initsem(int sid, int val);
static int P(int sid);
static int V(int sid);
static int closesem(int sid);
static int semgetval(int sid);
static int semcall(int sid, int op);
int semtran(key_t key)
{
int sid;
if ((sid=semget((key_t)key, 1, 0666))==-1) {
if ((sid=semget((key_t)key, 1, 0666|IPC_CREAT))==-1) {
ERRLOG("semget error no." << errno << " for key " << key);
return -1;
}
}
return (sid);
}
int initsem(int sid, int val)
{
union semun {
int val;
struct semid_ds *buf;
ushort *array;
} arg;
arg.val = val;
if (semctl(sid, 0, SETVAL, arg)==-1) {
ERRLOG("semctl setval error no." << errno);
return -1;
}
return 0;
}
int semgetval(int sid)
{
int val;
if ((val=semctl(sid, 0, GETVAL))==-1) {
ERRLOG("semctl getval error no." << errno);
}
return val;
}
int closesem(int sid)
{
if (semctl(sid, 0, IPC_RMID, NULL)==-1) {
ERRLOG("semctl rmid error no." << errno);
return -1;
}
return 0;
}
int semcall(int sid, int op)
{
if (sid==-1) {
err_msg("semcall invalid sem id");
return -1;
}
struct sembuf sb;
sb.sem_num = 0;
sb.sem_op = op;
sb.sem_flg = SEM_UNDO;
if (semop(sid, &sb, 1)==-1) {
ERRLOG("semop error no." << errno);
return -1;
}
return 0;
}
int P(int sid)
{
return semcall(sid, -1);
}
int V(int sid)
{
return semcall(sid, 1);
}
//
HIPC_SEM::HIPC_SEM()
{
key=0;
sid=-1;
}
HIPC_SEM::HIPC_SEM(key_t _key)
{
sid=-1;
key=_key;
open();
}
HIPC_SEM::HIPC_SEM(key_t _key, int val)
{
sid=-1;
key=_key;
open(val);
}
HIPC_SEM::~HIPC_SEM()
{
}
void HIPC_SEM::setkey(key_t _key)
{
key = _key;
open();
}
int HIPC_SEM::open()
{
if (!key) return -1;
if (sid!=-1) return sid;
sid = ::semtran(key);
return sid;
}
int HIPC_SEM::open(int val)
{
if (!key) return err_msg(-1, "sem key is NULL");
if (-1==sid) sid = ::semtran(key);
if (-1==sid) return -1; //err_msg(-1, "sem id is -1");
return init(val);
}
int HIPC_SEM::open(key_t _key, int val)
{
setkey(_key);
if (-1==sid) return -1;
return init(val);
}
int HIPC_SEM::init(int val)
{
if (-1==sid) return -1;
return ::initsem(sid, val);
}
int HIPC_SEM::close()
{
if (-1==sid) return -1;
return ::closesem(sid);
}
int HIPC_SEM::P()
{
if (-1==sid) return -1;
return ::P(sid);
}
int HIPC_SEM::V()
{
if (-1==sid) return -1;
return ::V(sid);
}
// shm 共享内存机制
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
HIPC_SHM::HIPC_SHM()
{
key = 0;
segid = -1;
addr = 0;
maxLength = SHM_MAXBYTES;
length = 0;
}
HIPC_SHM::HIPC_SHM(key_t _key)
{
segid = -1;
addr = 0;
maxLength = SHM_MAXBYTES;
length = 0;
setkey(_key);
}
HIPC_SHM::~HIPC_SHM()
{
}
int HIPC_SHM::setkey(key_t _key)
{
key = _key;
semSend.open(_key*2, 1);
semRecv.open(_key*2+1, 0);
return 0;
}
int HIPC_SHM::iskey(key_t _key)
{
return (key == _key);
}
key_t HIPC_SHM::getkey()
{
return key;
}
int HIPC_SHM::getsid()
{
return segid;
}
int HIPC_SHM::open()
{
if (!key)
return -2;
if (segid!=-1 && addr)
return 0;
if (segid==-1) {
segid = shmget(key, SHM_MAXBYTES, 0666|IPC_CREAT);
if (-1==segid) {
perror("shmget");
ERRLOG("shmget error no:"<<errno);
return 1;
//exit(1);
}
}
if (!addr) {
addr = (char*)shmat(segid, (char*)0, 0666);//|SHM_SHARE_MMU);
if ((long)addr==-1) {
addr = 0;
perror("shmat");
ERRLOG("shmat error no:"<<errno);
return 2;
//exit(2);
}
}
((shm_buf*)addr)->length = 0;
//cout << " open shm ok" << endl;
return 0;
}
int HIPC_SHM::close()
{
if (addr)
shmdt(addr);
if (-1!=segid)
{
if (-1==shmctl(segid, IPC_RMID, NULL)) {
perror("rmshm");
ERRLOG("shmctl rmid error no:"<<errno);
return 1;
//exit(1);
}
}
semSend.close();
semRecv.close();
return 0;
}
int HIPC_SHM::send(void *buf, int nbytes)
{
if (nbytes<0)
return -1;
if (nbytes>SHM_MAXBYTES)
nbytes=SHM_MAXBYTES;
if (!key || -1==segid || !addr)
return -2;
shm_buf * shmBuf = (shm_buf*)addr;
while (shmBuf->length) ;
semSend.P();
memcpy((char*)&shmBuf->content, buf, nbytes);
shmBuf->length = nbytes;
semSend.V();
//semRecv.V();
length = nbytes;
return nbytes;
}
int HIPC_SHM::recv(void *buf, int nbytes)
{
if (nbytes<0)
return -1;
if (nbytes>SHM_MAXBYTES)
nbytes=SHM_MAXBYTES;
if (!key || -1==segid || !addr)
return -2;
shm_buf * shmBuf = (shm_buf*)addr;
long Length = shmBuf->length;
if (Length>nbytes)
Length=nbytes;
if (!Length)
return 0;
//semRecv.P();
memcpy(buf, (char*)&shmBuf->content, Length);
//semSend.V();
shmBuf->length=0;
return Length;
}
void HIPC_SHM::show()
{
cout << "key:" << key << " sid:" << segid << " addr:" << (long)addr << endl;
}