我用QT編寫了一個共享內存環形緩衝區,我發現它在一個消費者和一個作者的單個進程中效果很好。如果我嘗試從第二個過程讀取數據,那麼第一個將連接崩潰的數據與seg故障相關聯。也許我忽略了一些東西?共享內存環形緩衝區崩潰
頭文件
#ifndef SHAREDMEMORYRINGBUFFER_H
#define SHAREDMEMORYRINGBUFFER_H
#include <QObject>
#include <QSharedMemory>
class SharedMemoryRingBuffer : public QObject
{
Q_OBJECT
public:
struct SharedMemoryAttributes {
int32_t readPosition;
int32_t writePosition;
int32_t size;
int32_t* data;
};
explicit SharedMemoryRingBuffer(QString sharedMemoryName, int32_t size, QObject *parent = 0);
~SharedMemoryRingBuffer();
int write(int32_t frame);
int32_t read();
int32_t length();
int32_t readPosition();
int32_t writePosition();
int avaibleSize();
int isEmpty();
void empty();
int isFull();
private:
SharedMemoryAttributes *_attributes;
int32_t _writePosition;
int32_t _readPosition;
int32_t _length;
QSharedMemory *_sharedMemory;
int _headSize;
signals:
void readFrame(QString name);
public slots:
};
#endif // SHAREDMEMORYRINGBUFFER_H
而CPP文件:
#include "sharedmemoryringbuffer.h"
#include <QDebug>
#define DEBUGGINGNAME "[SharedMemoryRingbuffer]"
SharedMemoryRingBuffer::SharedMemoryRingBuffer(QString sharedMemoryName, int32_t size, QObject *parent) : QObject(parent)
{
int sizeOfData = sizeof(int32_t) * (size);
int sizeOfHeader = sizeof(SharedMemoryAttributes);
_sharedMemory = new QSharedMemory(sharedMemoryName);
if (!_sharedMemory->attach()) {
if (!_sharedMemory->create(sizeOfData+sizeOfHeader, QSharedMemory::ReadWrite)) {
qDebug() << DEBUGGINGNAME << "Could not create shared memory object, aborting ...";
qDebug() << DEBUGGINGNAME << _sharedMemory->errorString();
//TODO: exit call
return;
}
}
_sharedMemory->lock();
_attributes = reinterpret_cast<SharedMemoryAttributes*>(_sharedMemory->data());
_attributes->readPosition = 0;
_attributes->writePosition = 0;
_attributes->size = size + 1;
_attributes->data = (int32_t*) _sharedMemory->data() + sizeOfHeader;
_sharedMemory->unlock();
}
SharedMemoryRingBuffer::~SharedMemoryRingBuffer()
{
_sharedMemory->detach();
delete _sharedMemory;
}
int SharedMemoryRingBuffer::write(int32_t frame)
{
_sharedMemory->lock();
if (!isFull()) {
_attributes->data[writePosition()] = frame;
if (writePosition() + 1 >= _attributes->size) _attributes->writePosition = 0;
else _attributes->writePosition += 1;
_sharedMemory->unlock();
return 1;
}
_sharedMemory->unlock();
return 0;
}
/**
* @brief SharedMemoryRingBuffer::read
* @return
* if the buffer is empty this functions returns the last readable value
*
*/
int32_t SharedMemoryRingBuffer::read()
{
_sharedMemory->lock();
int32_t frame = _attributes->data[readPosition()];
if (readPosition() != writePosition()) {
if (readPosition() + 1 >= _attributes->size) _attributes->readPosition = 0;
else _attributes->readPosition += 1;
emit readFrame(_sharedMemory->key());
}
_sharedMemory->unlock();
return frame;
}
int32_t SharedMemoryRingBuffer::length()
{
if(readPosition() <= writePosition()) {
return writePosition() - readPosition();
} else {
return readPosition() - writePosition();
}
}
int32_t SharedMemoryRingBuffer::readPosition()
{
return _attributes->readPosition;
}
int32_t SharedMemoryRingBuffer::writePosition()
{
return _attributes->writePosition;
}
int SharedMemoryRingBuffer::avaibleSize()
{
return -1;
}
int SharedMemoryRingBuffer::isEmpty()
{
if (readPosition() == writePosition()) return 1;
else return 0;
}
void SharedMemoryRingBuffer::empty()
{
}
int SharedMemoryRingBuffer::isFull()
{
if ((writePosition() + 1) % _attributes->size == readPosition()) return 1;
else return 0;
}
附註:我建議爲RAII您的MT鎖定在您的「寫入」功能中。例如:。 '_sharedMemory-> lock();'如果任何後續函數調用執行'throw',則鎖定不會被釋放。 – PaulMcKenzie