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