找回密码
 立即注册
收起左侧

关于共享内存的问题 QShareMemory

1
回复
5726
查看
[复制链接]
累计签到:56 天
连续签到:1 天
来源: 2015-3-2 14:37:53 显示全部楼层 |阅读模式
本帖最后由 侠隐 于 2015-3-2 17:27 编辑
  1. //.h文件
  2. #ifndef DIALOG_H
  3. #define DIALOG_H

  4. #include <QDialog>
  5. #include <QSharedMemory>

  6. namespace Ui {
  7. class Dialog;
  8. }

  9. class Dialog : public QDialog
  10. {
  11.     Q_OBJECT
  12.    
  13. public:
  14.     explicit Dialog(QWidget *parent = 0);
  15.     ~Dialog();
  16.    
  17. private:
  18.     Ui::Dialog *ui;
  19.     QSharedMemory shareMemory;
  20.     void detach();


  21. private slots:
  22.     void loadFromFile();
  23.     void loadFromMemory();
  24.     void on_pushButton_clicked();
  25.     void on_pushButton_2_clicked();
  26. };

  27. #endif // DIALOG_H
复制代码
  1. //.cpp文件
  2. #include "dialog.h"
  3. #include "ui_dialog.h"
  4. #include <QFileDialog>
  5. #include <QBuffer>
  6. #include <QDebug>

  7. Dialog::Dialog(QWidget *parent) :
  8.     QDialog(parent),
  9.     ui(new Ui::Dialog)
  10. {
  11.     ui->setupUi(this);
  12.     //在使用共享内存以前,需要先为其指定一个key,系统用它来作为底层共享内存段
  13.     //的标识。这个Key可以指定为任意的字符串。
  14.     shareMemory.setKey("QShareMemoryExample");
  15. }

  16. Dialog::~Dialog()
  17. {
  18.     delete ui;
  19. }

  20. void Dialog::detach()
  21. {
  22.     if(!shareMemory.detach()){
  23.         ui->label->setText(tr("无法从共享内存中分离"));
  24.     }
  25. }

  26. void Dialog::loadFromFile()
  27. {
  28.     //判断该进程是否已经连接到共享内存段
  29.     if(shareMemory.isAttached())
  30.         detach();  //先将该进程与共享内存段进行分离
  31.     ui->label->setText(tr("选择一个图片文件!"));
  32.     QString fileName = QFileDialog::getOpenFileName(0,QString(),QString(),
  33.                                                     tr("Images(*.png *.jpg)"));
  34.     QImage image;
  35.     if(!image.load(fileName)){
  36.         ui->label->setText(tr("选择的文件不是图片,请选择图片文件"));
  37.         return;
  38.     }

  39.     ui->label->setPixmap(QPixmap::fromImage(image));

  40.     //将图片加载到共享内存,使用QBuffer来暂存图片
  41.     QBuffer buffer;
  42.     buffer.open(QBuffer::ReadWrite);
  43.     QDataStream out(&buffer);
  44.     out<<image;
  45.     int size = buffer.size();
  46.     //创建指定大小的共享内存段,其大小是字节,该函数还会自动将共享内存段连接到本进程上
  47.     if(!shareMemory.create(size)){
  48.         ui->label->setText(tr("无法创建共享内存段"));
  49.         return;
  50.     }
  51.     //测试
  52.     if(shareMemory.isAttached()) qDebug()<<"haha";

  53.     shareMemory.lock(); //在进行共享内存段的操作期间,必须先进行加锁
  54.                         //等操作完成后,调用unlock()来进行解锁
  55.                         //这样在同一时间,就只能有一个进程允许操作共享内存段
  56.     //如果将最后一个连接在共享内存段上的进程进行分离,那么系统就会释放该共享内存段
  57.     //因为现在只有一个进程在共享内存段上,所以不能将它们进行分离
  58.     char* to = (char*)shareMemory.data();
  59.     const char* from = buffer.data().data();
  60.     memcpy(to,from,qMin(shareMemory.size(),size));
  61.     shareMemory.unlock();//进行解锁

  62. }

  63. void Dialog::loadFromMemory()
  64. {
  65.     if(shareMemory.isAttached()) qDebug()<<"haha";
  66.     //将进程连接到共享内存段
  67.     if(!shareMemory.attach()){
  68.         ui->label->setText(tr("无法连接到共享内存段,\n"
  69.                               "请先加载一张图片!"));
  70.         qDebug()<< shareMemory.errorString();
  71.         return;
  72.     }
  73.     QBuffer buffer;
  74.     QDataStream in(&buffer);
  75.     QImage image;

  76.     shareMemory.lock();
  77.     buffer.setData((char*)shareMemory.constData(),shareMemory.size());
  78.     buffer.open(QBuffer::ReadOnly);
  79.     in>>image;
  80.     shareMemory.unlock();

  81.     shareMemory.detach();
  82.     ui->label->setPixmap(QPixmap::fromImage(image));
  83. }

  84. void Dialog::on_pushButton_clicked()
  85. {
  86.     loadFromFile();
  87. }

  88. void Dialog::on_pushButton_2_clicked()
  89. {
  90.     loadFromMemory();
  91. }
复制代码
这里有一个问题不是很理解,我测试时,开启了一个窗口,也是一个进程,这里称线程1,然后从文件加载了一张图片,这个时候再从共享内存中显示图片,结果就是下面的无法连接的结果,如下个代码
然后再开一个新的进程,这里称线程2,这个时候可以从共享内存中显示图片
  1.     //无法连接的代码段
  2. if(shareMemory.isattached())  qDebug()<<"haha";
  3. if(!shareMemory.attach()){
  4.         ui->label->setText(tr("无法连接到共享内存段,\n"
  5.                               "请先加载一张图片!"));
  6.         qDebug()<< shareMemory.errorString();
  7.         return;
  8.     }
复制代码
从上图的代码看,我使用了QShareMemory::isAttached()测试得知此时线程1是有与共享内存连接的,
但是接下去的
    f(!shareMemory.attach())
却返回了true,也就是连接失败,这是为什么呢?
@yafeilinux

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

累计签到:69 天
连续签到:1 天
2016-8-22 00:02:04 显示全部楼层
你这问题挂这么久也没人解答,我来蹭下,我也刚学到这不懂啊
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

公告
可以关注我们的微信公众号yafeilinux_friends获取最新动态,或者加入QQ会员群进行交流:190741849、186601429(已满) 我知道了