zoukankan      html  css  js  c++  java
  • 多进程之间的互斥信号量的实现(Linux和windows跨平台)

            最近工作中遇到了一些关于文件读取权限的问题。当一个程序中对一个固定名称的文件做了读写的操作的时候,外界通过并发式的调用这个应用的时候,可能存在多个进程同时去操作这个文件,这个时候可能会造成调用失败的问题。所以这个时候,在操作文件之前就应该给该操作加锁,遵循先来先行,后来等待的效果,从而保证各个进程都能够正常的执行自己的功能。

            对于单个进程来说,进程内部的多个线程之间实现互斥的功能就方法很多,临界区(CriticalSection),互斥量(Mutex),信号量(Semaphore),事件(Event)等方式。其中临界区、互斥量、信号量都是严格意义上的实现互斥操作的,事件应该算是一种线程间的通信实现的互斥。

            在多线程中,可以直接将这些函数定义为全局变量直接去使用,但是对于进程而言,则不能这样做。

            多进程如果想实现互斥操作,那么只能使用互斥量(Mutex)的方式。

            Mutex分为匿名和命名互斥量,进程之间只能通过命名互斥实现。因为进程间回去检测同一个命名互斥对象在当前系统是否已经存在,如果存在,则需要等待,直到该互斥信息解除。如果匿名互斥,那么根本没法去检测到目标信息是哪一个,是否存在。

            windows下互斥操作包含几个函数:CreateMutex,WaitForSingleObject,ReleaseMutex,CloseHandle

            Linux下互斥包含几个函数:sem_open,sem_wait,sem_post,sem_close(关闭当前进程中的互斥量句柄,内核中依旧存在),sem_unlink(从内核中移除互斥量)

            下面封装了一个跨平台的实现多进程操作的类。

    //ProcessMutex.h文件: 
    #ifndef __PROCESS_MUTEX_H__
    #define __PROCESS_MUTEX_H__
     
    #ifdef WIN32
    #include <Windows.h>
    #endif
     
    #ifdef linux
    #include <unistd.h>
    #include <semaphore.h>
    #include <stdio.h>
    #include <fcntl.h>
    #include <signal.h>
    #include <string.h>
    #include <memory.h>
    #endif
     
    class CProcessMutex
    {
    public:
        /* 默认创建匿名的互斥 */
        CProcessMutex(const char* name = NULL);
        ~CProcessMutex();
     
        bool Lock();
        bool UnLock();
    private:
    #ifdef WIN32
        void* m_pMutex;
    #endif
    #ifdef linux
        set_t* m_pSem;
    #ednif
        char m_cMutexName[30];
    };
    #endif
     //ProcessMutex.cpp文件:
    #include "ProcessMutex.h"
     
    #ifdef WIN32
     
    CProcessMutex::CProcessMutex(const char* name)
    {
        memset(m_cMutexName, 0 ,sizeof(m_cMutexName));
        int min = strlen(name)>(sizeof(m_cMutexName)-1)?(sizeof(m_cMutexName)-1):strlen(name);
        strncpy(m_cMutexName, name, min);
        m_pMutex = CreateMutex(NULL, false, m_cMutexName);
    }
     
    CProcessMutex::~CProcessMutex()
    {
        CloseHandle(m_pMutex);
    }
     
    bool CProcessMutex::Lock()
    {
        //互斥锁创建失败
        if (NULL == m_pMutex)
        {
            return false;
        }
         
        DWORD nRet = WaitForSingleObject(m_pMutex, INFINITE);
        if (nRet != WAIT_OBJECT_0)
        {
            return false;
        }
     
        return true;
    }
     
    bool CProcessMutex::UnLock()
    {
        return ReleaseMutex(m_pMutex);
    }
     
    #endif
     
    #ifdef linux
     
    CProcessMutex::CProcessMutex(const char* name)
    {
        memset(m_cMutexName, 0 ,sizeof(m_cMutexName));
        int min = strlen(name)>(sizeof(m_cMutexName)-1)?(sizeof(m_cMutexName)-1):strlen(name);
        strncpy(m_cMutexName, name, min);
        m_pSem = sem_open(name, O_CREAT, 0644, 1);
    }
     
    CProcessMutex::~CProcessMutex()
    {
        int ret = sem_close(m_pSem);
        if (0 != ret)
        {
            printf("sem_close error %d
    ", ret);
        }
        sem_unlink(m_cMutexName);
    }
     
    bool CProcessMutex::Lock()
    {
        int ret = sem_wait(m_pSem);
        if (ret != 0)
        {
            return false;
        }
        return true;
    }
     
    bool CProcessMutex::UnLock()
    {
        int ret = sem_post(m_pSem);
        if (ret != 0)
        {
            return false;
        }
        return true;
    }
     
    #endif
    //使用方式
    CProcessMutex pMutex("MutexName");
    
    pMutex.Lock();
    
    
    //互斥内容或者函数
    
    pMutex.UnLock()

    这个只是最近工作中的一点收获,也算是自己的知识库也多了一点东西。

  • 相关阅读:
    C++ *和&
    leetcode 338. Bit位计数
    leetcode 216. 组合总和 III
    leetcode 40. 组合总和 II
    c++ vector 常用函数
    leetcode 491. 递增子序列
    leetcode 441. 排列硬币
    leetcode 258. 各位相加
    leetcode 415. 字符串相加
    leetcode 67. 二进制求和
  • 原文地址:https://www.cnblogs.com/ostin/p/9194621.html
Copyright © 2011-2022 走看看