67.QT-QSharedMemory


1.QSharedMemory介紹

QSharedMemory提供了多個線程和進程對共享內存段的訪問。它還提供了一種方法,讓單個線程或進程鎖定內存以進行獨占訪問。

當使用這個類時,請注意以下平台差異:

  • Windows: QSharedMemory不“擁有”共享內存段。當有QSharedMemory實例附加到特定共享內存段的所有線程或進程銷毀了它們的QSharedMemory實例或者退出了,Windows內核會自動釋放共享內存段。
  • Unix: QSharedMemory“擁有”共享內存段。當最后一個線程或進程將一個QSharedMemory實例附加到一個特定的共享內存段時,通過銷毀它的QSharedMemory實例從這個段中分離出來,Unix內核釋放這個共享內存段。但是如果最后一個線程或進程在沒有運行QSharedMemory析構函數的情況下崩潰了(未釋放),共享內存段會在崩潰時幸存下來。

在對共享內存進行讀寫操作之前,記得使用lock()鎖定共享內存,並且記得在操作完成后使用unlock()釋放鎖。

它的構造函數如下所示:

QSharedMemory(const QString &key, QObject *parent = nullptr)

 

通過指定的parent和key,構造一個共享內存對象。由於key已經被設置,所以不需要再調用setKey()或setNativeKey()指定要訪問的內存塊了,create()和attach()就可以被調用了。

其它常用函數如下所示:

QString QSharedMemory::key() const
//返回被setKey()所賦值的key如果未設置key則返回空字符串,如果應用程序是和非Qt平台的,則需要使用nativeKey()訪問

bool QSharedMemory::lock()
//用來鎖定共享內存的互斥值,鎖住成功則返回true. 若另一個進程已經鎖住了共享內存段,本函數將會阻塞直到鎖被另一個進程釋放。到那時,本函數才會獲得鎖並返回true. 如果本函數返回false,那就說明你已經忽略了一個由create()或attach()返回的false,而其原因可能是由於某個系統錯誤而導致setNativeKey()或QSystemSemaphore::acquire()失敗。

bool QSharedMemory::unlock()
//釋放共享內存段上的鎖並返回true,如果共享內存段沒有被lock,或者如果鎖被其他進程持有,本函數什么都不會做而只是返回false. 

 
bool QSharedMemory::create(int size, AccessMode mode=ReadWrite)
//創建一個大小為size個字節的共享內存段, 然后用給定的訪問模式mode附着到共享內存上。Mode取值有以下幾種:
QSharedMemory::ReadOnly : 共享內存段是只讀的。不允許寫入共享內存段。嘗試寫入使用ReadOnly創建的共享內存段會導致程序中止。
QSharedMemory::ReadWrite : 允許對共享內存段進行讀寫操作。

bool QSharedMemory::attach(AccessMode mode = ReadWrite)
//嘗試將進程附加到由傳遞給構造函數或調用setKey()或setNativeKey()的鍵標識的共享內存段上。默認訪問模式為“ReadWrite”。也可以是ReadOnly。如果附加操作成功,則返回true。如果返回false,則調用error()或者errorString()來確定發生了哪個錯誤。在附加共享內存段成功之后,則可以通過調用data()來獲得一個指向共享內存的指針。

bool QSharedMemory::isAttached() const
//如果該進程附加到共享內存段,則返回true。

bool QSharedMemory::detach()
//將進程從共享內存段中分離。如果這是連接到共享內存段的最后一個進程,那么共享內存段將被系統釋放,也就是說,內容將被銷毀。如果函數分離了共享內存段,則返回true。如果它返回false,通常意味着該段沒有連接,或者被另一個進程鎖定。

void * QSharedMemory::data()
//如果附加了共享內存段,則返回指向共享內存段內容的指針。否則返回null。在對共享內存進行讀寫操作之前,記得使用lock()鎖定共享內存,並且記得在操作完成后使用unlock()釋放鎖。

 

 

2.QSharedMemory示例

界面如下所示:

 

寫內存widget-示例代碼如下所示:

#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
#include <QTextEdit>
#include <QByteArray>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget),
      sharememory("shareTest", this)
{
    ui->setupUi(this);

}

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




void Widget::on_textEdit_textChanged()
{

    if(sharememory.isAttached()) {
        sharememory.detach();
    }
    QByteArray arr = ui->textEdit->toPlainText().toLocal8Bit();
    int len = arr.length();
    qDebug()<<ui->textEdit->toPlainText()<<len;
    if(!sharememory.create(len)) {
        qDebug() << sharememory.errorString();
        return ;
    }
    sharememory.lock();
    char *dest = reinterpret_cast<char *>(sharememory.data());
    for (int i = 0; i < len; i++) {
        dest[i] = arr[i];
    }
    sharememory.unlock();
}

 

 

 

讀內存widget-示例代碼如下所示:

#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
#include <QTextEdit>
#include <QTimer>
#include <QByteArray>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget),
      sharememory("shareTest", this)
{
    ui->setupUi(this);
    QTimer *timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(timeout()));
    timer->start(200);

}


void Widget::timeout()
{

    if (!sharememory.isAttached()) {
        if (!sharememory.attach()) {
            qDebug() << sharememory.errorString();
        } else {
            sharememory.lock();
            QByteArray arr((char*)sharememory.data(), sharememory.size());
            ui->textEdit->setPlainText(QString(arr));
            sharememory.unlock();
            sharememory.detach();
        }
    }

}

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

 

 

3.Linux下查看共享內存

1、查看共享內存,使用命令:ipcs -m

2、刪除共享內存,使用命令:ipcrm -m [shmid]

如下圖所示:

1、key:共享內存的key

2、shmid:共享內存的編號

3、owner:共享內存的創建用戶

4、perms:共享內存的權限

5、bytes:共享內存的大小

6、nattch:連接到共享內存的進程數

7、status:共享內存的狀態

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM