天天看點

對System V命名信号量的封裝類,用于程序/線程間互斥

最近為了對多程序互斥通路資源,采用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)

        p_buf.sem_op=-resNum;

void AOSLock::leaveN(int resNum)

        v_buf.sem_op=resNum;

void AOSLock::releaseLock()

        if(semctl(semId_,0,IPC_RMID)==-1)

int AOSLock::enterN_NO_WAIT(int 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)

        v_buf.sem_flg=IPC_NOWAIT;

繼續閱讀