Linux 互斥量Mutex 进程间共享

来源:互联网 发布:网络电梯五方对讲 编辑:程序博客网 时间:2024/06/11 11:00

        Mutex 本身是支持进程内和进程间两种类型的,平时在使用的时候用到的最多的还是进程内同步,昨天在看android framework的时候,发现其在barrier上还是使用了Mutex的进程间同步。实现方式还是蛮简单的,将pthread_mutex_t数据结构保存到共享内存上,从而实现多个进程共享同一内存,不像windows上指定一个名字就搞定了,废话少说,上代码:

//Mutex.h#ifndef CXX_MUTEX_H#define CXX_MUTEX_H#include <pthread.h>#include <string>using std::string;class Mutex {public:    enum {        MUTEX_PRIVATE = 0,  //process private        MUTEX_SHARE   = 1   //process shared    };    /**     * Constructor     * @param type: MUTEX_PRIVATE or MUTEX_SHARE     * @param name: if type=MUTEX_SHARE, name must be not null .     */    Mutex(int type, const char* name);    ~Mutex();    int  type() const;    /**     * @warnning:     *     if Mutex is shared in process, the process which create mutex must call this function     */    bool init();    /**     * @warnning:    *      If Mutex is shared in process, the process which create mutex must call this function     */    bool destroy();    bool lock();    bool unlock();    bool trylock();private:    bool  createDir(const char* dir);    bool  write(int fd, const char* buff, int len);    bool  saveShareMutexToFile();private:    int             m_type;    int             m_fd;    string          m_name;    pthread_mutex_t* m_mutex;};#endif//Mutex.cpp#include "Mutex.h"#include <unistd.h>#include <sys/mman.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <stdlib.h>#include <stdio.h>#include <errno.h>#define DBG_MSG(fmt, ...)   printf(fmt, ##__VA_ARGS__)static const char* s_MutexDir = "/tmp/mutex/";static const char* s_MutexSuffix = ".process.mutex"; Mutex::Mutex(int type, const char* name)    : m_type(type)    , m_fd(-1)    , m_mutex(NULL) {    if (MUTEX_PRIVATE == m_type) {        m_mutex = new pthread_mutex_t();        pthread_mutex_init(m_mutex, NULL);    }    else {        if (NULL == name) {            name = "default";        }        createDir(s_MutexDir);        m_name = s_MutexDir;        m_name += name;        m_name += s_MutexSuffix;    } } Mutex::~Mutex() {    if ((NULL != m_mutex) && (MUTEX_PRIVATE == m_type)) {        pthread_mutex_destroy(m_mutex);        delete m_mutex;        m_mutex = NULL;    }    if (MUTEX_SHARE == m_type) {        if (NULL != m_mutex) {            munmap(m_mutex, sizeof(pthread_mutex_t));            m_mutex = NULL;        }        if (-1  != m_fd) {            close(m_fd);            m_fd = -1;        }    }//if }int  Mutex::type() const{    return m_type;}bool Mutex::init(){    if(MUTEX_SHARE == m_type) {        if (0 != access(m_name.c_str(), F_OK) != 0) {            saveShareMutexToFile();        }        //open file and create shm        m_fd = open(m_name.c_str(), O_RDWR);        if (m_fd == -1) {            DBG_MSG("%s %d: error=%d\n", __FILE__, __LINE__, errno);            return false;        }        m_mutex = (pthread_mutex_t*)mmap(NULL, sizeof(pthread_mutex_t), PROT_READ|PROT_WRITE, MAP_SHAREDr, m_fd, 0);        if (-1l == (long)m_mutex) {            DBG_MSG("%s %d: error=%d\n", __FILE__, __LINE__, errno);            return false;        }    }    return true;}bool Mutex::destroy(){    if(NULL != m_mutex) {        pthread_mutex_destroy(m_mutex);    }}bool Mutex::lock(){    if (NULL == m_mutex) {        DBG_MSG("%s %d: m_mutex is null \n", __FILE__, __LINE__);        return false;    }    return (0 == pthread_mutex_lock(m_mutex));}bool Mutex::unlock(){    if (NULL == m_mutex) {        DBG_MSG("%s %d: m_mutex is null \n", __FILE__, __LINE__);        return false;    }    return (0 == pthread_mutex_unlock(m_mutex));}bool Mutex::trylock(){    if (NULL == m_mutex) {        DBG_MSG("%s %d: m_mutex is null \n", __FILE__, __LINE__);        return false;    }    return (0 == pthread_mutex_trylock(m_mutex));}bool Mutex::createDir(const char* dir){    if(NULL == dir) {        return false;    }    if (0 != access(s_MutexDir, F_OK)) {        string cmd = "mkdir -p ";        cmd += dir;        system(cmd.c_str());    }    return true;}bool Mutex::write(int fd, const char* buff, int len){    int writeNum = 0;    while((len - writeNum) > 0) {        writeNum += ::write(fd, buff + writeNum, len - writeNum);    }    return true;}bool Mutex::saveShareMutexToFile(){     //write data to file    pthread_mutexattr_t mutexattr;    pthread_mutex_t mutex;    pthread_mutexattr_init(&mutexattr);    pthread_mutexattr_setpshared(&mutexattr,PTHREAD_PROCESS_SHARED);    pthread_mutex_init(&mutex, &mutexattr);    int fd = open(m_name.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);    write(fd, (const char*)&mutex, sizeof(pthread_mutex_t));    close(fd);    pthread_mutex_destroy(&mutex);}


推荐使用方式:通常一个系统是由多个process组成的,其中根据其角色又分为前期初始化、事务处理、后期清理。建议在前期初始化的时候讲所有的用于进程间共享的Mutex前部初始化(init),在系统后期清理掉时候再将所有的共享Mutex销毁(destroy)。

Mutex用于进程间互斥,杀伤力比较大,一个进程出问题了导致锁没有释放,结果其他进程也会受到波及,建议尽量不要使用Mutex用做进程间互斥!

0 0
原创粉丝点击