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、一个进程卡死,锁住共享内存,则另一个进程无法写入,导致两个进程同时卡死。这个问题暂时解决方式是发送和接收都为一个独立的线程中实现,防止卡住主线程。