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())
- {
- qDebug()<<tr("can't attach share memory");
- }
- QBuffer buffer;
- QDataStream in(&buffer);
- QPixmap pixMap;
- shareMemory.lock();
- qDebug()<<shareMemory.size();
- buffer.setData((char*)shareMemory.constData(),shareMemory.size());
- buffer.open(QBuffer::ReadWrite);
- in>>pixMap;
- shareMemory.unlock();
- shareMemory.detach();
- ui->label->setPixmap(pixMap);
- }