【Qt】QSharedMemory类详解

00. 目录

01. 概述

QSharedMemory提供了多个线程和进程对共享内存段的访问。它还提供了一种方法,让单个线程或进程锁定内存以进行独占访问。

当使用这个共享内存类时,请注意以下平台差异:

Windows:QSharedMemory 不“拥有”共享内存段。当所有具有连接到特定共享内存段的 QSharedMemory 实例的线程或进程已销毁其 QSharedMemory 实例或退出时,Windows 内核会自动释放共享内存段。

Unix:QSharedMemory“拥有”共享内存段。当将 QSharedMemory 实例附加到特定共享内存段的最后一个线程或进程通过销毁其 QSharedMemory 实例与该段分离时,Unix 内核会释放共享内存段。但是如果最后一个线程或进程在没有运行 QSharedMemory 析构函数的情况下崩溃,共享内存段会在崩溃中幸存下来。

HP-UX:每个进程只允许一个连接到共享内存段。这意味着 QSharedMemory 不应跨 HP-UX 中同一进程中的多个线程使用。

记得在对共享内存进行读写之前用lock ()锁住共享内存,完成后记得用unlock ()释放锁。

当 QSharedMemory 的最后一个实例与段分离时,QSharedMemory 会自动销毁共享内存段,并且不会保留对该段的引用。

警告

除非另有说明,否则 QSharedMemory 以特定于 Qt 的方式更改密钥。与非 Qt 应用程序的互操作是通过首先使用 QSharedMemory() 创建默认共享内存,然后使用 setNativeKey() 设置本机密钥来实现的。使用本机密钥时,共享内存不受对其多次访问的保护(例如,无法锁定()),应使用用户定义的机制来实现这种保护。

02. 公有类型

在这里插入图片描述

03. 成员方法

在这里插入图片描述

成员方法概述

QSharedMemory::QSharedMemory(const QString &key, QObject *parent = nullptr)
使用给定的父对象构造一个共享内存对象,并将其键设置为key。因为它的key被设置了,它的create ()attach ()函数就可以调用了。    
    
QSharedMemory::QSharedMemory(QObject *parent = nullptr)
此函数重载 QSharedMemory()。
使用给定的parent构造一个共享内存对象。共享内存对象的键不是由构造函数设置的,因此共享内存对象没有附加底层共享内存段。
在调用`create()`或者attach()之前必须使用setKey()或者setNativeKey()设置Key.

    
[virtual] QSharedMemory::~QSharedMemory()
析构函数清除Key,这会强制共享内存对象与其底层共享内存段分离。如果此共享内存对象是最后一个连接到共享内存段的对象,
则detach () 操作会销毁共享内存段。
    
bool QSharedMemory::attach(QSharedMemory::AccessMode mode = ReadWrite)
尝试将进程关联到由传递给构造函数或调用setKey ()setNativeKey ()的密钥标识的共享内存段。
访问方式默认为ReadWrite。
它也可以是ReadOnly。true如果附加操作成功则返回。如果返回false,则调用error ()来判断发生了哪个错误。
附加共享内存段后,
可以通过调用data ()获得共享内存的指针。    
    
const void *QSharedMemory::constData() const
返回一个指向共享内存段内容的常量指针,如果有的话。否则返回空值。记得在对共享内存进行读写之前用lock ()锁住共享内存,
完成后记得用unlock ()释放锁。
    
bool QSharedMemory::create(int size, QSharedMemory::AccessMode mode = ReadWrite)
使用传递给构造函数的键创建大小为size字节的共享内存段,使用setKey () 或使用setNativeKey ()设置key,
然后使用给定的访问模式
关联到新的共享内存段并返回true。如果key标识的共享内存段已经存在,则不执行attach操作并false返回。当返回值为 时false,
调用error ()来判断发生了哪个错误。    
    
void *QSharedMemory::data()    
返回一个指向共享内存段内容的指针,如果有的话。否则返回空值。记得在对共享内存进行读写之前用lock ()锁住共享内存,
完成后记得用unlock ()释放锁。
    
const void *QSharedMemory::data() const
此函数重载 data()。
    
    
bool QSharedMemory::detach()
从共享内存段中分离进程。如果这是最后一个附加到共享内存段的进程,那么共享内存段将被系统释放,即内容被销毁。
true如果它分离共享内存段,则该函数返回。如果它返回false,通常意味着该段没有被附加,或者它被另一个进程锁定。
    
QSharedMemory::SharedMemoryError QSharedMemory::error() const
返回一个值,该值指示是否发生了错误,如果发生了,则是哪个错误。
    
QString QSharedMemory::errorString() const
返回最后发生的错误的文本描述。如果error () 返回错误值,则调用此函数以获取描述错误的文本字符串。
    
    
bool QSharedMemory::isAttached() const
返回true此进程是否附加到共享内存段。
    
QString QSharedMemory::key() const    
返回用setKey ()分配给这个共享内存的键,如果没有分配键,或者段使用nativeKey () ,则返回空键。
密钥是 Qt 应用程序用来标识共享内存段的标识符。

您可以通过调用nativeKey ()找到操作系统使用的本机、特定于平台的key。    
    
bool QSharedMemory::lock()
这是一个信号量,它锁定共享内存段以供此进程访问并返回true。如果另一个进程锁定了该段,则该函数将阻塞,
直到锁定被释放。然后它获取锁并返回true。如果此函数返回false,则表示您忽略了来自create ()attach ()
的 false 返回,您已使用setNativeKey ()设置key或QSystemSemaphore::acquire () 由于未知系统错误而失败。    
    
QString QSharedMemory::nativeKey() const
返回此共享内存对象的本机、特定于平台的key。本机key是操作系统用来标识共享内存段的标识符。
您可以使用本机key访问不是由 Qt 创建的共享内存段,或授予非 Qt 应用程序共享内存访问权限。    
    
void QSharedMemory::setKey(const QString &key)
为这个共享内存对象设置平台无关的键。如果key与当前 key 相同,则函数不执行任何操作就返回。
您可以调用key () 来检索平台无关的密钥。在内部,QSharedMemory将此密钥转换为特定于平台的密钥。
如果您改为调用nativeKey (),您将获得特定于平台的转换后的密钥。
如果共享内存对象附加到底层共享内存段,它将在设置新密钥之前与其分离。这个函数不做attach ()void QSharedMemory::setNativeKey(const QString &key)
设置此共享内存对象的本机、特定于平台的键。如果key与当前本机 key 相同,则该函数不执行任何操作就返回。
如果您只想为段分配一个键,则应改为调用setKey ()。
您可以调用nativeKey () 来检索本机密钥。如果已分配本机键,则调用key () 将返回空字符串。
如果共享内存对象附加到底层共享内存段,它将在设置新密钥之前与其分离。这个函数不做attach ()。
如果您设置本机密钥,该应用程序将不可移植。
 
 
int QSharedMemory::size() const    
返回附加共享内存段的大小。如果没有附加共享内存段,则返回 0。
注意:段的大小可能大于传递给create ()的请求大小。
    
    
bool QSharedMemory::unlock()
如果该进程当前持有该锁,则释放共享内存段上的锁并返回true。如果该段没有被锁定,或者如果该锁定被另一个进程持有,
则什么都不会发生并且返回 false。    
    
    
    

04. 程序示例一

程序示例

#include <QCoreApplication>


#include <QSharedMemory>
#include <QDebug>


int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);


    //共享内存对象
    QSharedMemory shareMemory;

    //设置共享内存的键 没有设置key之前默认为空
    qDebug() << "Key: " << shareMemory.key();

    //设置共享内存的Key
    shareMemory.setKey("Qt");
    qDebug() << "Key: " << shareMemory.key();

    //默认共享内存是没有关联的
    qDebug() << "isAttached: " << shareMemory.isAttached();

    //对应Key的共享内存不存在,因此关联失败
    qDebug() << shareMemory.attach();
    qDebug() << shareMemory.errorString();

    //判断该进程是否与共享内存关联
    if (shareMemory.isAttached())
    {
        if (!shareMemory.detach())
        {
            qDebug() << shareMemory.errorString();
            return -1;
        }
    }


    //默认读写的方式创建共享内存 创建的同时自动关联到该共享内存
    if (!shareMemory.create(1024))
    {
        qDebug() << shareMemory.errorString();
        return -1;
    }

    qDebug() << "isAttached: " << shareMemory.isAttached();
    qDebug() << "size: " << shareMemory.size();


    //加锁
    qDebug() << "lock: " << shareMemory.lock();

    //获取共享内存的起始地址
    void *data = shareMemory.data();
    qDebug() << "Addr: " << data;

    //拷贝数据
    memcpy(data, "hello", strlen("hello"));

    //解锁
    qDebug() << "unlock: " << shareMemory.unlock();

    //解除与共享内存的关联
    qDebug() << "detach: " << shareMemory.detach();


    return 0;
}

执行结果

Key:  ""
Key:  "Qt"
isAttached:  false
false
"QSharedMemory::handle: doesn't exist"
isAttached:  true
size:  4096
lock:  true
Addr:  0x29d0000
unlock:  true
detach:  true

05. 程序示例二

读写示例

#include <QCoreApplication>


#include <QSharedMemory>
#include <QDebug>


/*
编程思路

共享内存中数据提供方:
A、定义QSharedMemory shareMemory,并设置标志名shareMemory.setKey();
B、将共享内存与主进程分离 shareMemory.detach();
C、创建共享内存 shareMemory.create();
D、将共享内存上锁shareMemory.lock();
E、将进程中要共享的数据拷贝到共享内存中;
F、将共享内存解锁shareMemory.unlock();


共享内存中数据使用方:
A、定义QSharedMemory shareMemory,并设置与共享内存提供方一致的标志名shareMemory.setKey()。
B、将共享内存与主进程绑定shareMemory.attach(),使主进程可以访问共享内存的数据;
C、将共享内存上锁shareMemory.lock();
D、从共享内存中取数据;
E、使用完后将共享内存解锁shareMemory.unlock(),并将共享内存与进程分离shareMemory.detach();
*/




int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);


    void *data = nullptr;

    const void *str = "好好学习,天天向上";

    //共享内存对象
    QSharedMemory shareMemory;



    //---------------写共享内存-----------------
    //1. 设置共享内存key
    shareMemory.setKey("Kitty");


    //2. 判断进程是否与共享内存已经关联,如果已经关联就解除关联
    if (shareMemory.isAttached())
    {
        if (!shareMemory.detach())
        {
            qDebug() << shareMemory.errorString();
            return -1;
        }
        else
        {
            qDebug() << "共享内存关联成功";
        }
    }


    //3. 创建共享内存,同时关联共享内存
    if (shareMemory.create(1024))
    {
        qDebug() << "创建共享内存成功";
    }
    else
    {
        qDebug() << shareMemory.errorString();
        return -1;
    }

    //4. 将共享内存上锁
    shareMemory.lock();


    //5. 拷贝数据到共享内存
    data = shareMemory.data();
    if (nullptr == data)
    {
        qDebug() << shareMemory.errorString();
        shareMemory.unlock();
        return -1;
    }

    memcpy(data, str, strlen(static_cast<const char *>(str)));



    //6.解锁共享内存
    if (!shareMemory.unlock())
    {
        qDebug() << shareMemory.errorString();
        return -1;
    }


    //---------------读共享内存-----------------
    //7. 将共享内存上锁
    shareMemory.lock();

    data = nullptr;

    //8. 拷贝数据
    data = shareMemory.data();

    qDebug() << static_cast<char *>(data);

    //9. 解锁共享内存
    if (!shareMemory.unlock())
    {
        qDebug() << shareMemory.errorString();
        return -1;
    }

    return 0;
}

执行结果

16:12:46: Starting D:\\ProgramData\\Qt\\build-1TestShareMemrory-Desktop_Qt_5_15_2_MinGW_64_bit-Debug\\
debug\\1TestShareMemrory.exe ...
创建共享内存成功
好好学习,天天向上

06. 源码下载

下载:1TestShareMemrory.rar

07. 附录

7.1 Qt教程汇总
网址:https://dengjin.blog.csdn.net/article/details/115174639

© 版权声明
THE END
喜欢就支持一下吧
点赞717 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容