Qt提供了一种安全的共享内存的实现QSharedMemory,以便在多线程和多进程编程中安全的使用。比如说QQ的聊天的客户端,这里有个个性头象,当点击QQ音乐播放器的时候,启动QQ音乐播放器(启动一QQ音乐播放器的进程)这时QQ音乐播放器里也有一个个性头像,这两者间的头像一样,现用共享内存的方法实现。
先说下实现共享内存的步骤,然后用一具体的实例说明。
向共享内存中提供数据的一方:
1,定义QSharedMemory shareMemory,并设置标志名shareMemory.setKey();
2,将共享内存与主进程分离 shareMemory.detach();
3,创建共享内存 shareMemory.create();
4,将共享内存上锁shareMemory.lock();
5,将进程中要共享的数据拷贝到共享内存中;
6,将共享内存解锁shareMemory.unlock();
从共享内存中取数据的一方:
1,定义QSharedMemory shareMemory,并设置共享内存的标志名shareMemory.setKey()注意设置的要与提供内存共享的一方要一样。
2,将共享内存上锁shareMemory.lock();
3,将共享内存与主进程绑定shareMemory.attach(),使该进程可以访问共享内存的数据;
4,从共享内存中取数据;
5,使用完后将共享内存解锁shareMemory.unlock(),另外将共享内存与该进程分离shareMemory.detach();
下面贴段代码来说明:
A 向共享内存中提供数据的一方
main.cpp #include <QtGui/QApplication> #include "widget.h" int main(int argc, char *argv[]) { QApplication a(argc, argv); Widget w; w.show(); return a.exec(); }
widget.h ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include <QSharedMemory> namespace Ui { class Widget; } class Widget : public QWidget { Q_OBJECT public: explicit Widget(QWidget *parent = 0); ~Widget(); private slots: void on_pushButton_clicked(); void on_pushButton_2_clicked(); private: Ui::Widget *ui; QSharedMemory shareMemory;//注意该变量不要在函数内局部定义,由于函数内的局部变量随着函数执行结束而消失 }; #endif // WIDGET_H
widget.cpp #include "widget.h" #include "ui_widget.h" #include <QFileDialog> #include <QBuffer> #include <QDebug> #include <QProcess> Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); shareMemory.setKey("share"); } Widget::~Widget() { delete ui; } void Widget::on_pushButton_clicked() { if(shareMemory.isAttached()) { shareMemory.detach();//将该进程与共享内存段分离 } QString filename = QFileDialog::getOpenFileName(this); QPixmap pixMap; pixMap.load(filename); ui->label->setPixmap(pixMap); QBuffer buffer; QDataStream out(&buffer); buffer.open(QBuffer::ReadWrite); out<<pixMap; qDebug()<<buffer.size(); int size = buffer.size(); if(!shareMemory.create(size)) { qDebug()<<tr("can't create memory segment"); qDebug()<<shareMemory.error(); return; } qDebug()<<shareMemory.size(); shareMemory.lock(); char *to = (char*)shareMemory.data(); const char *from = (char*)buffer.data().data(); memcpy(to,from,qMin(size,shareMemory.size()));//数据从该进程中拷贝到共享数据内存中 shareMemory.unlock();//共享内层解锁 }
B 从共享内存中取数据的一方:
main.cpp #include <QtGui/QApplication> #include "widget.h" int main(int argc, char *argv[]) { QApplication a(argc, argv); Widget w; w.show(); return a.exec(); }
widget.h #ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include <QSharedMemory> namespace Ui { class Widget; } class Widget : public QWidget { Q_OBJECT public: explicit Widget(QWidget *parent = 0); ~Widget(); private slots: void on_pushButton_clicked(); private: Ui::Widget *ui; QSharedMemory shareMemory; }; #endif // WIDGET_H
widget.cpp #include "widget.h" #include "ui_widget.h" #include <QBuffer> #include <QDebug> Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); shareMemory.setKey("share");//设置标志一定要与共享内存的标志一样 this->on_pushButton_clicked(); } Widget::~Widget() { delete ui; } void Widget::on_pushButton_clicked() { if(!shareMemory.attach())//将shareMemory与该进程绑定使之可以访问shareMemory里的内容 { qDebug()<<tr("can't attach share memory"); } QBuffer buffer; QDataStream in(&buffer); QPixmap pixMap; shareMemory.lock();//给shareMemory枷锁 qDebug()<<shareMemory.size(); buffer.setData((char*)shareMemory.constData(),shareMemory.size());//将shareMemeory里的数据放到buffer里 buffer.open(QBuffer::ReadWrite); in>>pixMap; shareMemory.unlock();//将shareMemory解锁 shareMemory.detach();//将shareMemeory与该进程分离 ui->label->setPixmap(pixMap); }