对System V命名信号量的封装类,用于进程/线程间互斥
2007-11-06 14:09
351 查看
最近为了对多进程互斥访问资源,采用System V的命名信号量,为了方便使用,对其用c++进行了封装,代码如下.
AOSLock.hpp:
#ifndef _AOSLOCK_HPP
#define _AOSLOCK_HPP
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <fcntl.h>
typedef enum
{
SEM_FAIL=-1,
SEM_OK,
SEM_BUSY
} SEM_RET_VALUE;
union semun
{
int val;
struct semid_ds* buf;
};
class AOSLock
{
private:
int semId_;
key_t key_;
int resNum_;
public:
AOSLock();
AOSLock(const char* keyPathName);
int initialLock(int resNum);
int getVal();
void enter1();
void leave1();
void enterN(int resNum);
void leaveN(int resNum);
int enterN_NO_WAIT(int resNum); // return SEM_BUSY or SEM_OK or SEM_FAIL
void leaveN_NO_WAIT(int resNum);
void releaseLock();
};
#endif
AOSLock.cpp:
#include "AOSLock.hpp"
AOSLock::AOSLock()
{
key_ = ftok("/root", 1);
}
AOSLock::AOSLock(const char* keyPathName)
{
key_ = ftok(keyPathName, 1);
}
int AOSLock::initialLock(int resNum)
{
semId_ = semget(key_, 1, 0666|IPC_CREAT|IPC_EXCL);
// printf("sem id=%d/n",semId_);
if (semId_ < 0)
{
//perror("semget");
// int tmpErrno = errno;
//printf("errno=%d, expected=%d/n", errno, EEXIST);
//if (tmpErrno == EEXIST)
{
// printf("exist/n");
semId_ = semget(key_, 1, 0666|IPC_CREAT);
}
}
else
{
// printf("first time/n");
resNum_ = resNum;
union semun arg;
arg.val=resNum;
if (semctl(semId_, 0, SETVAL, arg) < 0)
{
// perror("semctl");
}
}
// printf("sem id_ =%d/n",semId_);
/* int value = semctl(semId_, 0, GETVAL);
if (value < 0)
{
perror("semctl");
}
printf("sem value=%d/n", value);*/
return semId_;
}
int AOSLock::getVal()
{
int value = semctl(semId_, 0, GETVAL);
if (value < 0)
{
// perror("semctl");
}
// printf("sem value=%d/n", value);
return value;
}
void AOSLock::enter1()
{
struct sembuf p_buf;
p_buf.sem_num=0;
p_buf.sem_op=-1;
p_buf.sem_flg=SEM_UNDO;
semop(semId_,&p_buf,1);
}
void AOSLock::leave1()
{
struct sembuf v_buf;
v_buf.sem_num=0;
v_buf.sem_op=1;
v_buf.sem_flg=SEM_UNDO;
semop(semId_,&v_buf,1);
}
void AOSLock::enterN(int resNum)
{
struct sembuf p_buf;
p_buf.sem_num=0;
p_buf.sem_op=-resNum;
p_buf.sem_flg=SEM_UNDO;
semop(semId_,&p_buf,1);
}
void AOSLock::leaveN(int resNum)
{
struct sembuf v_buf;
v_buf.sem_num=0;
v_buf.sem_op=resNum;
v_buf.sem_flg=SEM_UNDO;
semop(semId_,&v_buf,1);
}
void AOSLock::releaseLock()
{
if(semctl(semId_,0,IPC_RMID)==-1)
perror("semctl");
}
int AOSLock::enterN_NO_WAIT(int resNum)
{
struct sembuf p_buf;
p_buf.sem_num=0;
p_buf.sem_op=-resNum;
p_buf.sem_flg=IPC_NOWAIT;
if (semop(semId_,&p_buf,1) < 0)
{
if(errno == EAGAIN)
{
return SEM_BUSY;
}
else
{
return SEM_FAIL;
}
}
return SEM_OK;
}
void AOSLock::leaveN_NO_WAIT(int resNum)
{
struct sembuf v_buf;
v_buf.sem_num=0;
v_buf.sem_op=resNum;
v_buf.sem_flg=IPC_NOWAIT;
semop(semId_,&v_buf,1);
}
AOSLock.hpp:
#ifndef _AOSLOCK_HPP
#define _AOSLOCK_HPP
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <fcntl.h>
typedef enum
{
SEM_FAIL=-1,
SEM_OK,
SEM_BUSY
} SEM_RET_VALUE;
union semun
{
int val;
struct semid_ds* buf;
};
class AOSLock
{
private:
int semId_;
key_t key_;
int resNum_;
public:
AOSLock();
AOSLock(const char* keyPathName);
int initialLock(int resNum);
int getVal();
void enter1();
void leave1();
void enterN(int resNum);
void leaveN(int resNum);
int enterN_NO_WAIT(int resNum); // return SEM_BUSY or SEM_OK or SEM_FAIL
void leaveN_NO_WAIT(int resNum);
void releaseLock();
};
#endif
AOSLock.cpp:
#include "AOSLock.hpp"
AOSLock::AOSLock()
{
key_ = ftok("/root", 1);
}
AOSLock::AOSLock(const char* keyPathName)
{
key_ = ftok(keyPathName, 1);
}
int AOSLock::initialLock(int resNum)
{
semId_ = semget(key_, 1, 0666|IPC_CREAT|IPC_EXCL);
// printf("sem id=%d/n",semId_);
if (semId_ < 0)
{
//perror("semget");
// int tmpErrno = errno;
//printf("errno=%d, expected=%d/n", errno, EEXIST);
//if (tmpErrno == EEXIST)
{
// printf("exist/n");
semId_ = semget(key_, 1, 0666|IPC_CREAT);
}
}
else
{
// printf("first time/n");
resNum_ = resNum;
union semun arg;
arg.val=resNum;
if (semctl(semId_, 0, SETVAL, arg) < 0)
{
// perror("semctl");
}
}
// printf("sem id_ =%d/n",semId_);
/* int value = semctl(semId_, 0, GETVAL);
if (value < 0)
{
perror("semctl");
}
printf("sem value=%d/n", value);*/
return semId_;
}
int AOSLock::getVal()
{
int value = semctl(semId_, 0, GETVAL);
if (value < 0)
{
// perror("semctl");
}
// printf("sem value=%d/n", value);
return value;
}
void AOSLock::enter1()
{
struct sembuf p_buf;
p_buf.sem_num=0;
p_buf.sem_op=-1;
p_buf.sem_flg=SEM_UNDO;
semop(semId_,&p_buf,1);
}
void AOSLock::leave1()
{
struct sembuf v_buf;
v_buf.sem_num=0;
v_buf.sem_op=1;
v_buf.sem_flg=SEM_UNDO;
semop(semId_,&v_buf,1);
}
void AOSLock::enterN(int resNum)
{
struct sembuf p_buf;
p_buf.sem_num=0;
p_buf.sem_op=-resNum;
p_buf.sem_flg=SEM_UNDO;
semop(semId_,&p_buf,1);
}
void AOSLock::leaveN(int resNum)
{
struct sembuf v_buf;
v_buf.sem_num=0;
v_buf.sem_op=resNum;
v_buf.sem_flg=SEM_UNDO;
semop(semId_,&v_buf,1);
}
void AOSLock::releaseLock()
{
if(semctl(semId_,0,IPC_RMID)==-1)
perror("semctl");
}
int AOSLock::enterN_NO_WAIT(int resNum)
{
struct sembuf p_buf;
p_buf.sem_num=0;
p_buf.sem_op=-resNum;
p_buf.sem_flg=IPC_NOWAIT;
if (semop(semId_,&p_buf,1) < 0)
{
if(errno == EAGAIN)
{
return SEM_BUSY;
}
else
{
return SEM_FAIL;
}
}
return SEM_OK;
}
void AOSLock::leaveN_NO_WAIT(int resNum)
{
struct sembuf v_buf;
v_buf.sem_num=0;
v_buf.sem_op=resNum;
v_buf.sem_flg=IPC_NOWAIT;
semop(semId_,&v_buf,1);
}
相关文章推荐
- 【Linux系统编程】进程同步与互斥:System V 信号量
- linux 命名信号量实现进程间的互斥与同步
- [linux系统编程]System V IPC 信号量做进程间互斥
- Python进阶(3)_进程与线程中的lock(线程中互斥锁、递归锁、信号量、Event对象、队列queue)
- linux网络编程之System V 信号量(二):用信号量实现进程互斥示例和解决哲学家就餐问题
- 进程与线程;同步与互斥:事件,信号量,临界区,互斥量
- linux网络编程之System V 信号量(二):用信号量实现进程互斥示例和解决哲学家就餐问题
- 进程/线程通信_信号量与互斥锁_笔记
- 进程与线程,信号量与互斥量的区别
- C++windows内核编程笔记day13 进程、线程与信号量
- 进程与线程(7) 进程间通信之信号量 (java os)
- Windows平台下的进程/线程的同步与互斥
- 用信号量实现进程互斥示例和解决哲学家就餐问题
- System.IO命名空间,用于文件/流的处理。
- 进程、线程、信号量、互斥锁的一个简单解释
- System.IO系列:局域网内多线程使用命名管道在进程之间通信实例
- SDL的关于线程中互斥锁的条件变量的封装
- 关于SWAP指令用于实现多CPU的互斥信号量
- 用C++封装Win32信号量,同步线程
- 一起talk C栗子吧(第一百零二回:C语言实例--使用信号量进行进程间同步与互斥三)