window API一天一练之共享内存

    今天学习win下共享内存的进程通信,仿照Qt的共享内存类,封装了一个简单的类。虽然比不上Qt的类那么完善和强大,但是通过学习也达到了理解win共享内存的方式。

class WinSharedMemory
{
public:
	WinSharedMemory(string szkey = "");
	~WinSharedMemory();

	bool CreateSize(int size);
	void *Data();
	const void *ConstData() const;
	bool Attach();
	bool Detach();
	bool IsAttach();
	bool Lock();
	bool UnLock();
	int  Size();
	void Setkey(string szKey);
	string Key();
	string GetErrorMessage();
protected:
	void cleanHandle();
private:
	string     m_errorMessage;
	int        m_size;
	string     m_memKey;
	bool       m_isLock;
	HANDLE     m_mutex; 
	HANDLE     m_fileMapping;
	void      *m_pMemory;
};
WinSharedMemory::WinSharedMemory( string szkey /*= ""*/ ):m_memKey(szkey)
	,m_isLock(false),m_mutex(NULL),m_pMemory(NULL),m_size(0),m_fileMapping(NULL)
{
}

WinSharedMemory::~WinSharedMemory()
{
	this->Setkey("");
}

bool WinSharedMemory::CreateSize( int size )
{
	if (m_memKey == "")
	{
		m_errorMessage = "没有设置共享内存名";
		return false;
	}
	if (size < 1)
	{
		m_errorMessage = "设置内存大小必须大于0";
		return false;
	}
	m_size = size;
	m_fileMapping = CreateFileMapping(INVALID_HANDLE_VALUE,NULL,PAGE_READWRITE,0,m_size,m_memKey.c_str());
	if (m_fileMapping == NULL)
	{
		m_errorMessage ="创建共享内存失败";
		return false;
	}
	if (GetLastError() == ERROR_ALREADY_EXISTS)
	{
	
		m_errorMessage ="共享内存已存在";
		return false;
	}
	return true;
}

void * WinSharedMemory::Data()
{
	return m_pMemory;
}

const void * WinSharedMemory::ConstData() const
{
	return m_pMemory;
}

bool WinSharedMemory::Attach()
{
	if (m_fileMapping)
	{
		m_pMemory = (void *)MapViewOfFile(m_fileMapping,FILE_MAP_ALL_ACCESS,0,0,0);
		if (m_pMemory == NULL)
		{
			m_errorMessage = "映射内存失败";
			return false;
		}
	}
	
	return true;
}

bool WinSharedMemory::Lock()
{
	if (!m_isLock)
	{
		string szMutexkey = m_memKey + "_mutex";
		m_mutex = CreateMutex(NULL,false,szMutexkey.c_str());
		WaitForSingleObject(m_mutex,INFINITE);
		m_isLock = true;
	}
	else
	{
		m_errorMessage = "内存已被锁定";
		return false;
	}
}

bool WinSharedMemory::IsAttach()
{
	return  (m_pMemory != NULL);;
}

bool WinSharedMemory::UnLock()
{
	if (m_isLock)
	{
		ReleaseMutex(m_mutex);
		m_isLock = false;
	}
	return true;
}

int WinSharedMemory::Size()
{
	return m_size;
}

void WinSharedMemory::Setkey( string szKey )
{
	m_memKey = szKey;
}

string WinSharedMemory::Key()
{
	return m_memKey;
}

string WinSharedMemory::GetErrorMessage()
{
	return m_errorMessage;
}

bool WinSharedMemory::Detach()
{
	if (!UnmapViewOfFile(m_pMemory))
	{
		m_errorMessage = "释放共享内存失败";
		return false;
	}
	m_size = 0;
	m_pMemory = NULL;
	cleanHandle();
	return true;
}

void WinSharedMemory::cleanHandle()
{
	if (m_fileMapping)
	{
		CloseHandle(m_fileMapping);
		m_fileMapping = NULL;
	}
	if (m_mutex)
	{
		CloseHandle(m_mutex);
		m_mutex = NULL;
	}
}


Qt的测速程序代码:

SharedMemory::SharedMemory(QWidget *parent, Qt::WFlags flags)
	: QDialog(parent, flags)
{
	m_pWriteDataBtn = new QPushButton(tr("WriteData"),this);
	m_pReadDataBtn = new QPushButton(tr("ReadData"),this);
	m_pTextEdit = new QTextEdit(this);

	connect(m_pReadDataBtn,SIGNAL(clicked()),this,SLOT(ReadDataFromMemorySlot()));
	connect(m_pWriteDataBtn,SIGNAL(clicked()),this,SLOT(WriteDataToMemorySlot()));
	
	//ui.setupUi(this);
}

SharedMemory::~SharedMemory()
{

}

void SharedMemory::ReadDataFromMemorySlot()
{
	int size = 1024 * 1024 ;
	WinSharedMemory sharedMemory;
	sharedMemory.Setkey("FileMapObject");
	if (sharedMemory.IsAttach())
	{
		sharedMemory.Detach();
	}
	sharedMemory.CreateSize(size);
	sharedMemory.Attach();
	sharedMemory.Lock();
	char *pmemory = (char*)sharedMemory.Data();
	char *pText = new char[size];
	strcpy(pText,pmemory);
	sharedMemory.UnLock();
	sharedMemory.Detach();
	m_pTextEdit->setText(QString::fromStdString(pText));
}

void SharedMemory::WriteDataToMemorySlot()
{
	int size = 1024 * 1024 ;
	WinSharedMemory sharedMemory;
	sharedMemory.Setkey("FileMapObject");
    if (sharedMemory.IsAttach())
	{
		sharedMemory.Detach();
	}
	sharedMemory.CreateSize(size);
	sharedMemory.Attach();
	sharedMemory.Lock();
	char *pmemory = (char*)sharedMemory.Data();
	string text = m_pTextEdit->toPlainText().toStdString();
	strcpy(pmemory,text.c_str());
	sharedMemory.UnLock();
	
}

void SharedMemory::resizeEvent( QResizeEvent *event )
{
	this->setFixedSize(QSize(500,300));
	m_pReadDataBtn->setGeometry(0,0,100,20);
	m_pReadDataBtn->setGeometry(120,0,100,20);
	m_pTextEdit->setGeometry(0,25,500,270);
}


左边的程序进行写入数据,右边读取。经过验证,可以进行通信。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值