Salve gente.
Piccolo esempietto con le librerie Qt: serializziamo e condividiamo fra due processi un QHash via QSharedMemory.
Spero che l’esempio sia chiaro. Per testarlo, lanciare due volte il programma (in due terminali diversi).
Ciau! ^^
Codice d’esempio
/**
* FILE : QHashInShm.cpp
* AUTHOR : Gian Paolo "JP" Ghilardi (http://rejex.wordpress.com)
* LICENSE : released under the terms of GPL v2.0 ("only")
* COMPILE : via QtCreator (choose Qt Console Application template)
* PURPOSE : simple Qt-based example showing how to serialize/deserialize
* a QHash object and write/read it from shared memory
* TEST : launch two time this program in a terminal. The first one
* will start writing data to shared memory ("writer process")
* while the second will read and print it ("reader process")
*
* TESTED ON :
* - MacOSX 10.5.8, PPC 32-bit, G++ 4.0.1, Qt Libs 4.6 (QtCreator 1.3)
*
* REFERENCES:
* [1]: http://en.wikipedia.org/wiki/Shared_memory
* [2]: http://en.wikipedia.org/wiki/Serialization
* [3]: http://doc.trolltech.com/4.6/ipc-sharedmemory.html
* [4]: http://efforts.embedded.ufcg.edu.br/qt/?p=145
*/
#include <QtCore/QCoreApplication>
#include <QBuffer>
#include <QDebug>
#include <QSharedMemory>
#include <QHash>
#define OUT // used to visually remember objects to be filled
// before returning from a function
typedef QHash<QString, QString> QDict; // for easy manipulation
/**
* Serializes data in a QDict object and writes them to a QSharedMemory object
* @param shm reference to a valid QSharedMemory object (created by caller)
* @param source const reference to the QDict object to be serialized and
* written into the shared memory
* @param createShm flag used to require space into the shared memory
* (default is false - no shared memory creation)
* @return true if all operations succeeded; false otherwise
*/
bool writeToShm(OUT QSharedMemory &shm,
const QDict &source,
bool createShm = false)
{
QBuffer buffer;
QDataStream out(&buffer);
buffer.open(QBuffer::ReadWrite); // data serialization
out << source;
int size = buffer.size();
if (createShm && !shm.create(size)) // shared memory creation (if requested)
{
qDebug() << "Error while creating the shared memory!";
return false;
}
shm.lock();
char *to = (char*)shm.data(); // writing serialized data to shared mem
const char *from = buffer.data().data();
memcpy(to, from, qMin(shm.size(), size));
shm.unlock();
return true;
}
/**
* Deserializes data read from shared memory to a QDict object
* @param shm reference to a valid QSharedMemory object (created by caller)
* @param destination reference to a QDict object that will receive
* the deserialized data read from the shared memory
* @return true if all operations succeeded; false otherwise
*/
bool readFromShm(QSharedMemory &shm,
OUT QDict &destination)
{
QBuffer buffer;
QDataStream in(&buffer);
shm.lock();
buffer.setData((char*)shm.constData(), shm.size()); // deserialization
buffer.open(QBuffer::ReadOnly);
in >> destination;
shm.unlock();
return true;
}
/**
* Starting function for this program. If you launch this program two times, the
* first "instance" will create the shared memory object and will periodically
* write values in it; the second "instance" will read those values from the
* shared memory and will print them on screen.
*/
int main(int argc, char *argv[])
{
QDict dict;
QSharedMemory shm("QDictInShm");
qDebug() << "Simple Qt example showing how to share a QHash object via shm";
if(shm.attach()) // "reader process" part
{
qDebug() << "[Reader Process]";
for(int i=0; i<4; i++)
{
qDebug() << "- reading from shm:";
readFromShm(shm, dict);
foreach(QString key, dict.keys())
qDebug() << " [" << key << "]: " << dict[key];
qDebug() << "";
sleep(5);
}
// job done. if writer finished and detached, shm will now be
// automaticaly freed at this point, )
shm.detach();
}
else // "writer process" part
{
dict.insert("A", "AValue");
dict.insert("B", "BValue");
dict.insert("i", QString::number(0));
dict.squeeze(); // compact/reclaim unused space
qDebug() << "[Writer Process]";
qDebug() << "- creating shm segment and writing into it...";
writeToShm(shm, dict, true);
for(int i=1; i<4; i++)
{
sleep(5);
dict["i"] = QString::number(i); // change the value (space allocated unchanged)
qDebug() << "- writing into shm...";
writeToShm(shm, dict);
}
// job done. if the reader process is still attached,
// shm won't be freed until it finishes
shm.detach();
}
return EXIT_SUCCESS;
}
Il codice in esecuzione
Questo è l’output del programma in esecuzione (si notino i due terminali aperti, uno per ciascun processo)…
