IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> Linux进程间通信之共享内存锁,包括C++11的事件,信号量 -> 正文阅读

[C++知识库]Linux进程间通信之共享内存锁,包括C++11的事件,信号量

Event.h

#pragma once
#include <mutex>
#include <condition_variable>
#include <chrono>
#include <string>
#include <memory>
#include <stdio.h>
#include <iostream>
#include <pthread.h>

#ifndef _WIN32
#include <unistd.h>
#include <semaphore.h>
#include <stdio.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/stat.h>
#include <sys/shm.h>

#else
#include <Windows.h>
#endif

using namespace std;

//事件
class Event 
{ // No signal when init
public:
	void Wait() 
	{
		std::unique_lock<std::mutex> lker(m_mtx);
		m_cv.wait(lker);
	}

	bool Wait(int nMillSec) 
	{
		std::chrono::milliseconds mills(nMillSec);
		std::unique_lock<std::mutex> lker(m_mtx);
		auto ret = m_cv.wait_for(lker, mills);
		return (ret != std::cv_status::timeout);
	}

	void NotifyOne() 
	{
		m_cv.notify_one();
	}
	void NotifyAll() 
	{
		m_cv.notify_all();
	}

private:
	std::mutex m_mtx;
	std::condition_variable m_cv;
};


//信号量
class Semaphore 
{
public:
	Semaphore(int nCount = 0) :m_count(nCount) {}

	void Wait() 
	{
		std::unique_lock<std::mutex> lker(m_mtx);
		m_cv.wait(lker, [this]() {return m_count > 0; });
		--m_count;
	}

	void Signal() 
	{
		{
			std::unique_lock<std::mutex> lker(m_mtx);
			++m_count;
		} // 通知前解锁,避免获取信号后因得不到锁重新进入等待
		m_cv.notify_one();
	}

private:
	int m_count;
	std::mutex m_mtx;
	std::condition_variable m_cv;
};



//共享内存进程锁
class name_mutex
{
public:
	name_mutex(string name, int id) 
	{
		
#ifndef _WIN32
		m_cMutexName = name;

		key_t shmKey = ftok(m_cMutexName.c_str(), id);//创建IPC对象的键值key,即共享内存的键值
		size_t MAPPING_SIZE = 512;
		if((m_mfd = shmget(shmKey, MAPPING_SIZE, IPC_CREAT|IPC_EXCL|0666)) == -1)//成功返回共享内存的ID,失败返回-1
		{
			m_mfd = shmget(shmKey, MAPPING_SIZE, 0) ;//最后一个参数为0表示取共享内存标识符
		}
		
		//printf("Class Mutex: shmget OK, devName=%s, id=%d, mfd=%d, pMutex=%x, shmKey=%x\n",m_cMutexName.c_str(),id,m_mfd,m_pMutex,shmKey);
		
		if(m_mfd == -1)
			m_pMutex = NULL;
		else
		{
			m_pMutex = (pthread_mutex_t*)shmat(m_mfd , NULL , 0);//对共享内存进行映射,如果成功,返回共享内存基地址,出错返回-1
			
			pthread_mutexattr_t mutex_attr;
			pthread_mutexattr_init(&mutex_attr);
			pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE_NP);
			pthread_mutexattr_setpshared(&mutex_attr, PTHREAD_PROCESS_SHARED);
			pthread_mutex_init(m_pMutex, &mutex_attr);
		}
#else		
	   
		m_cMutexName = name+to_string(id);		
		m_pMutex = CreateMutex(NULL, FALSE, m_cMutexName.c_str());
#endif		

		if (m_pMutex == NULL)
		{
			//printf("CreateMutex Name=%s(%d) ERROR\n", m_cMutexName.c_str(),id);
		}
		else
		{
		   // printf("CreateMutex Name=%s(%d) OK\n", m_cMutexName.c_str(),id);
		}

	}

	~name_mutex() 
	{
#ifndef _WIN32
		if(m_pMutex == NULL)
			return ;
		pthread_mutex_destroy(m_pMutex);


		//当使用 IPC_RMID 后
		//SHM 并不会被真正删除,要等到 shm_nattch 等于 0 时才会被真正 删除。IPC_RMID 只是为删除做准备,而不是立即删除。
		shmdt(m_pMutex);//解除共享内存的映射,
		
		shmid_ds ds_buf;
		shmctl(m_mfd, IPC_STAT, &ds_buf);//获取属性信息,放置到 buf 中
		
		//printf("Class name_mutex: ~name_mutex: nattach=%d, mfd=%d\n",ds_buf.shm_nattch,mfd);
		if(ds_buf.shm_nattch == 0)
		{
			shmctl(m_mfd, IPC_RMID , NULL);//将共享内存标记为“即将被删除”状态
			//printf("Class name_mutex: ~name_mutex OK: mfd=%d\n",mfd);
		}
		m_pMutex = NULL ;

#else
		CloseHandle(m_pMutex);
#endif
	}


	void lock()
	{
		        
#ifndef _WIN32
		pthread_mutex_lock(m_pMutex);
#else
		WaitForSingleObject(m_pMutex, INFINITE);
#endif
	}

	void unlock()
	{
#ifndef _WIN32
		pthread_mutex_unlock(m_pMutex);
#else
		ReleaseMutex(m_pMutex);
#endif     
	}

	int trylock(unsigned int times)
	{
		int ret = -1;
		
#ifndef _WIN32
		for(int i=0; i<times; i++)
		{
			ret = pthread_mutex_trylock(m_pMutex);
			if(ret == 0) break;
			usleep(500);
		}
#else
		ret = WaitForSingleObject(m_pMutex, times);
#endif     
		return ret;
	}


#ifndef _WIN32

	pthread_mutex_t *m_pMutex;
	int m_mfd;
	
#else
	
	void* m_pMutex;
	
#endif

private:
	string m_cMutexName;
       
};



class name_lock
{
public:
	name_lock(shared_ptr<name_mutex> mtx)//构造函数
	{
		m_mtx = mtx;
		m_mtx->lock();
	}

	~name_lock()//析构函数
	{
		m_mtx->unlock();
	}

private:
    shared_ptr<name_mutex> m_mtx;
};

main.cpp

#include "Event.h"
#include <stdio.h>
#include <stdlib.h> 
#include <unistd.h>  
#include <string.h>  
#include <signal.h> 
#include <strings.h> 
#include <sys/types.h> 
#include <sys/ipc.h> 
#include <sys/shm.h>

int main()
{	
	shared_ptr<name_mutex>	m_mtxDevice;
	m_mtxDevice.reset(new name_mutex("MUTEX",1));//用共享指针对new出来的这个对象进行管理

	while(true)
	{
		{
			name_lock lg(m_mtxDevice);//加锁
			
		
			do something.... //开多个进程,访问同一个资源,而不会有问题
			
		} 
		
	}
}

编译:

g++ -std=gnu++11 main.cpp -lpthread
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-04-27 11:09:20  更:2022-04-27 11:10:02 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/21 0:18:21-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码