進程通信學習--Qt共享內存使用

Qt提供了共享內存的封裝<QSharedMemory>,使用步奏相比windows的方式要簡單的多。

按照寫入和讀取部分:

寫入部分:

	QSharedMemory _sharedMemory;//聲明
	_sharedMemory.setKey("SharedMemoryTest");//設置訪問密鑰
	bool isAttached = _sharedMemory.isAttached();//判斷內存是否被關聯
	if (!isAttached)//若被關聯
	{
		bool isDetach = _sharedMemory.detach();//如果關聯,先斷開
		if (!isDetach)//斷開失敗
		{
			QMessageBox::warning(this,"提示","共享內存被關聯鎖定!");
		}
	}
	QBuffer buffer;//設置緩衝區
	QDataStream qdsm(&buffer);
	buffer.open(QBuffer::ReadWrite);//設置讀寫方式
	qdsm << strData;//往緩衝區寫入數據
	int size = buffer.size();
	if(!_sharedMemory.create(size))//檢測共享內存段是否創建成功 
	{
		qDebug() << _sharedMemory.errorString();
	}
	_sharedMemory.lock();//鎖住共享內存
	char *to = (char*)_sharedMemory.data();//準備好要被共享的空間
	int minsize=_sharedMemory.size();
	const char *from = "8889";//準備要被共享的數據
	memcpy(to, from, qMin(_sharedMemory.size(), size));//往共享空間中存入共享數據
	_sharedMemory.unlock();//解鎖

讀取部分(以下代碼設立在了一根獨立線程中,所以可以採用無限循環的方式,可以採用其他方式調用接收):

    QSharedMemory revMemory;
	IPCServer* server = (IPCServer*)object;
	//聲明共享內存的密鑰和讀出來的字符串
	QString key,readstring;
	//聲明緩衝區
	QBuffer buffer;
	//聲明數據流
	QDataStream out(&buffer);
	//輸入密鑰	
	revMemory.setKey("SharedMemoryTest");
	while (1)
	{	
 		//找到指定的共享內存後關聯此內存 
		if (!revMemory.attach())
		{
			QFile file("ErrorLog.txt");
			if (file.open(QIODevice::WriteOnly| QIODevice::Append))
			{
				file.write(QString("共享內存關聯失敗\n").toAscii());
			}

		}
		
		//鎖上共享內存。
		revMemory.lock();
		//用緩衝區得到共享內存關聯後得到的數據和數據大小
		char* temp=(char *)revMemory.constData();
		if (temp)
		{
			emit server->RevMessage(QString::fromLocal8Bit(temp));

		}
		//解鎖共享內存空間 
		revMemory.unlock();
		//與共享內存空間分離 
		revMemory.detach();
		
		Sleep(100);
    }

常見問題:

1、實現讀寫同步

在剛做不久的項目要求中,讀寫速度很快,每秒超過300次通信,且要求做到不能丟包。實現方式採用寫入時通過另一種IPC方式當作信號傳輸,告訴讀取端接受信號。這另一種方式可以採用信號量或QLocalSocket。但也有問題:當發送方速度比接收方快,接收方會出現粘包的情況,也就是在接收信號傳輸過程中,共享內存中在不斷寫入。可以通過傳輸buffer的拼接來化解。

2、一個進程卡死,鎖住共享內存,則另一個進程無法寫入,導致兩個進程同時卡死。這個問題暫時解決方式是發送和接收都爲一個獨立的線程中實現,防止卡住主線程。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章