使用 QSharedMemory 附加现有的共享内存

Posted

技术标签:

【中文标题】使用 QSharedMemory 附加现有的共享内存【英文标题】:Attach existing Shared Memory with QSharedMemory 【发布时间】:2017-02-22 11:54:15 【问题描述】:

在应用程序 1(C 代码)中,我创建了一个这样的共享内存:

char * key_path = "/tmp/shmem";

int file = open(key_path, O_CREAT | O_RDWR | O_APPEND, 0755);
close(file);
key_t key = ftok(key_path, 1);

shmid = shmget (key, SHM_DATASIZE , IPC_CREAT | SHM_R | SHM_W);
shmdata = shmat(shmid, NULL, 0);shmid);

在 Application 2(QT) 中我想访问这个 SharedMemory

const char* native_key = "/tmp/shmem";

key_t ft_key = ftok(native_key, 1);
key = QString::number(ft_key);

QSharedMemory shmem(key);
if(!shmem.attach()) 
    qDebug() << "attach failed" << shmem.errorString()  << shmem.key() << shmem.nativeKey() << endl;

附加失败“QSharedMemory::attach (shmget): 不存在”“16858191”“/tmp/qipc_sharedmemory_24384b85e5d54b23bd4f84f14de71b10d4801666”

所以我尝试了以下方法

const char* native_key = "/tmp/shmem";

key_t ft_key = ftok(native_key, 1);
key = QString::number(ft_key);

QSharedMemory shmem(key);
shmem.setNativeKey(native_key);
if(!shmem.attach()) 
    qDebug() << "attach failed" << shmem.errorString()  << shmem.key() << shmem.nativeKey() << endl;

附加失败“QSharedMemory::attach (shmget): 不存在”“” "/tmp/shmem_prot"

我看了一下qsharedmemory_unix.cpp的出处

我认为问题在于 unix_key 未设置,因此 attach() 中的 shmget 将失败。 handle() 是私有的,所以我不能调用这个函数来设置 unix_key。

是否可以在不知道共享内存大小/调用 create() 的情况下访问共享内存?

当我尝试调用 create() 时

QSharedMemory shmem(key);
shmem.create(SHM_DATASIZE);

将创建一个新的共享内存...

我做错了什么?提前致谢。

【问题讨论】:

我认为有两件事可能会导致问题。一,当你结束记忆时,你会分离记忆吗?二、是否使用信号量信号来防止同时多次访问内存?对于附件,我不知道您可以使用不需要区域大小的任何功能。但是“也许”你可以尝试用一个整数(或其他东西)创建另一个区域来保持第一个的大小。然后用它来附加它。祝你好运 什么操作系统?假设您有ipcs 实用程序,ipcs -a 的输出是什么?这应该会显示您机器上的所有 SysV 共享内存段。 @koksalb 我们可以讨论共享内存成功附加时的分离和信号量。但是在这种状态下,这并不重要.. @AndrewHenle 我正在使用 Linux Mint。我已经在使用ipcs了。 0x01013c3f 1048586 mvollmer 600 23720 1 0x13013c51 1507340 mvollmer 600 23720 1 1048586由Application 1创建,1507340由QT创建。 【参考方案1】:

您访问的不是同一个共享内存段。 Qt 修改了你传递给它的密钥,结果是不同的密钥,因此是共享内存 id。

Per the QSharedMemory documentation:

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

您似乎需要使用QSharedMemory 创建共享内存段,使用setNativeKey() 设置一个新密钥,然后从QSharedMemory 外部附加到该内存。

【讨论】:

感谢您指出这一点。但这不起作用。 setNativeKey() 正在分离新创建的共享内存。 QSharedMemory shmem(key); shmem.create(SHM_DATASIZE); shmem.setNativeKey(native_key); 所以似乎不可能访问不是由 QSharedMemory 创建的共享内存。唯一的方法是使用 QSharedMemory 创建一个 SharedMemory 并从其他应用程序访问它。这有点奇怪。 @mvollmer 如果您可以从 QSharedMemory 段中获取实际密钥并将其传递给您的非 Qt 应用程序,那么该应用程序应该能够直接使用该密钥。在 Qt 中创建段后,you can use ipcs -m 可查看所有共享内存段的详细信息。

以上是关于使用 QSharedMemory 附加现有的共享内存的主要内容,如果未能解决你的问题,请参考以下文章

Qt进程间通信之QSharedMemory示例

Qt进程间通信之QSharedMemory示例

如何更改 QSharedMemory 的大小

QSharedMemory共享内存实现进程间通讯(IPC)及禁止程序多开

Qt QSharedMemory 和 QDataStream

QT:QSharedMemory 正在使用相同的键创建多个段