1. 程式人生 > >Qt QSharedMemory共享記憶體的使用

Qt QSharedMemory共享記憶體的使用

可用於程序間通訊。

建立物件:利用QSharedMemory類建立例項物件時,必須為該共享記憶體指定關鍵字(即為該共享記憶體起一個名字)。只有當共享記憶體被設定了關鍵字之後,才可以執行建立create()、關聯attach()等操作。為共享記憶體指定關鍵字有兩種方法:

SharedMemory* sharememory;

sharememory = newQSharedMemory("QSharedMemoryExample");

還有一種方式:

SharedMemory* sharememory;

sharememory = new QSharedMemory();

sharememory->setKey("QSharedMemoryExample ");

bool QSharedMemory::create ( int size, AccessMode mode =ReadWrite )
為QSharedMemory類例項物件建立一個空間大小為size的共享記憶體,該記憶體空間預設的訪問方式為可讀可寫。共享記憶體建立成功返回true,否則返回false。QSharedMemory類定義一個列舉類變數AccessMode,指定了兩種共享記憶體的訪問方式:

QSharedMemory::ReadOnly   只讀方式訪問共享記憶體

QSharedMemory::ReadWrite  讀寫方式訪問共享記憶體

注意,create會自動attach程序。

3、關聯共享記憶體

bool QSharedMemory::attach ( AccessMode mode =ReadWrite )
將以關鍵字key命名的共享記憶體和當前程式進行關聯,共享記憶體預設的訪問方式為可讀可寫。如果程式和共享記憶體關聯成功,返回true,否則返回false。

 

4、分離共享記憶體

bool QSharedMemory::detach ()
解除共享記憶體和程式的關聯,即呼叫該函式後,程式不可以再訪問共享記憶體。如果該共享記憶體被多個程式例項所關聯,當最後一個程式例項和共享記憶體解除關聯後,該共享記憶體將由作業系統自動釋放掉。分離操作成功,返回true。如果返回false,通常意味著該共享記憶體和程式分離失敗,或者其他程式當前正在訪問該共享記憶體,分離操作執行失敗。


5、判斷共享記憶體的關聯狀態

bool QSharedMemory::isAttached ()const
該函式用來判斷程式(呼叫該函式的程式)是否和共享記憶體進行關聯,是返回true,否返回false。


6、設定/獲取共享記憶體的關鍵字

QString QSharedMemory::key ()const                                 //獲取共享記憶體關鍵字
Qt應用程式通過關鍵字來辨識共享記憶體。key ()函式用來獲取共享記憶體的關鍵字,如果沒有指定例項物件的關鍵字,或者共享記憶體的關鍵字是由nativeKey ()函式指定的話,則返回空。 

void QSharedMemory::setKey (const QString & key )        //設定共享記憶體關鍵字
setKey ()函式用來為共享記憶體段設定關鍵字(為共享記憶體命名),如果引數key的值和建構函式或者之前指定的關鍵字相同的話,則該函式將不做任何操作,直接返回。
 

7、鎖定/解鎖共享記憶體

bool QSharedMemory::lock ()                    //鎖定共享記憶體
如果共享記憶體資源當前處於釋放狀態,程序呼叫該函式將共享記憶體中的資源鎖定,並返回true。其他程序將不能訪問該共享記憶體。如果共享記憶體被其他程序佔用時,則該函式會一直處於阻塞狀態,直到其他程序使用完畢,釋放共享記憶體資源。
bool QSharedMemory::unlock ()         //解鎖共享記憶體
如果共享記憶體資源被當前程序所佔有,呼叫該函式將解鎖該共享資源,並返回true。如果當前程序沒有佔用該資源,或者共享記憶體被其他程序訪問,則不做任何操作並返回false。

 

為了保證共享記憶體中資料的完整性,當一個程序在讀寫共享記憶體的時候,其他程序不允許對該共享區域進行訪問。QSharedMemory類提供了lock()函式和unlock()函式來實現這一共享記憶體訪問機制。某一程式對共享記憶體進行讀寫操作之前,需要呼叫lock()函式鎖定該共享記憶體,之後獨享共享記憶體中的資料,並對資料進行讀寫等操作。共享記憶體訪問完畢,呼叫unlock()函式,釋放共享記憶體的使用許可權。

8、錯誤原因

SharedMemoryError QSharedMemory::error ()const 
當共享記憶體出錯時,呼叫該函式顯示相應的錯誤程式碼。
QString QSharedMemory::errorString ()const
當共享記憶體出錯時,呼叫該函式,以文字形式顯示錯誤原因。

9、獲取共享記憶體的地址

const void *QSharedMemory::constData ()const
void * QSharedMemory::data ()

const void *QSharedMemory::data ()const          //過載函式
程式關聯共享記憶體的前提下,呼叫該函式返回共享記憶體中資料的起始地址。如果沒有關聯共享記憶體,則返回0。

 

10、獲取共享記憶體的大小

int QSharedMemory::size ()const
呼叫該函式將返回程式所關聯的共享記憶體的大小(位元組)。如果沒有關聯的共享記憶體,則返回0。

#include "dialog.h"
#include "ui_dialog.h"
#include <QFileDialog>
#include <QBuffer>
#include <QDebug>

Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);

    sharedMemory.setKey("liuzhichao");
}

Dialog::~Dialog()
{
    delete ui;
}

void Dialog::loadFromFile()
{
    if (sharedMemory.isAttached())
        detach();
    ui->label->setText(tr("選擇一個圖片檔案!"));
    QString fileName = QFileDialog::getOpenFileName(0, QString(), QString(),
                                                    tr("Images (*.png *.jpg)"));
    QImage image;
    if (!image.load(fileName)) {
        ui->label->setText(tr("選擇的檔案不是圖片,請選擇圖片檔案!"));
        return;
    }
    //ui->label->setPixmap(QPixmap::fromImage(image));

    // 將圖片載入到共享記憶體
    QBuffer buffer;
    buffer.open(QBuffer::ReadWrite);
    QDataStream out(&buffer);
    out << image;
    int size = buffer.size();
    if (!sharedMemory.create(size)) {
        ui->label->setText(tr("無法建立共享記憶體段!"));
        return;
    }
    sharedMemory.lock();
    char *to = (char*)sharedMemory.data();
    const char *from = buffer.data().data();
    memcpy(to, from, qMin(sharedMemory.size(), size));
    sharedMemory.unlock();
}

void Dialog::loadFromMemory()
{
//    if (!sharedMemory.attach()) {
//        ui->label->setText(tr("無法連線到共享記憶體段,\n"
//                              "請先載入一張圖片!"));
//        return;
//    }
    if(!sharedMemory.isAttached())
        sharedMemory.attach();
    QBuffer buffer;
    QDataStream in(&buffer);
    QImage image;

    sharedMemory.lock();
    buffer.setData((char*)sharedMemory.constData(), sharedMemory.size());
    buffer.open(QBuffer::ReadOnly);
    in >> image;
    sharedMemory.unlock();

    sharedMemory.detach();
    ui->label->setPixmap(QPixmap::fromImage(image));
}

void Dialog::detach()
{
    if (!sharedMemory.detach())
        ui->label->setText(tr("無法從共享記憶體中分離!"));
}


void Dialog::on_loadFromFileButton_clicked()
{
    loadFromFile();
}

void Dialog::on_loadFromSharedMemoryButton_clicked()
{
    loadFromMemory();
}