使用 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 附加现有的共享内存的主要内容,如果未能解决你的问题,请参考以下文章
QSharedMemory共享内存实现进程间通讯(IPC)及禁止程序多开