如何从Qt连接到现有共享内存?
我用C语言中的二进制代码创建了一个共享内存段,并将一些数据写入其中。现在我想从Qt读取数据。如何从Qt连接到现有共享内存?如何从Qt连接到现有共享内存?,qt,shared-memory,Qt,Shared Memory,我用C语言中的二进制代码创建了一个共享内存段,并将一些数据写入其中。现在我想从Qt读取数据。如何从Qt连接到现有共享内存?QSharedMemory实际上并不意味着与其他任何东西互操作。在Unix上,它是通过SYSV共享内存实现的,但它将特定于Qt的参数传递给ftok: ::ftok(filename.constData(), qHash(filename, proj_id)); 您可以在C代码中模拟这种行为,但我认为没有必要 不打开共享内存段,只需将文件映射到内存,并从多个进程访问它。在Qt
QSharedMemory
实际上并不意味着与其他任何东西互操作。在Unix上,它是通过SYSV共享内存实现的,但它将特定于Qt的参数传递给ftok
:
::ftok(filename.constData(), qHash(filename, proj_id));
您可以在C代码中模拟这种行为,但我认为没有必要
不打开共享内存段,只需将文件映射到内存,并从多个进程访问它。在Qt上,QFile::map
执行您需要的操作
下面的示例显示了两种技术:使用SYSV共享内存和使用内存映射文件:
// https://github.com/KubaO/stackoverflown/tree/master/questions/sharedmem-interop-39573295
#include <QtCore>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <cerrno>
#include <stdexcept>
#include <string>
void mmap_test() {
QTemporaryFile shmFile;
check(shmFile.open(), "shmFile.open");
shmFile.write({sizeof(Data), 0});
check(true, shmFile, "shmFile.write");
check(shmFile.flush(), shmFile, "shmFile.flush");
// SYSV MMAP
Handle fd{open(QFile::encodeName(shmFile.fileName()), O_RDWR)};
check(fd.fd, "open");
auto ptr1 = mmap(NULL, sizeof(Data), PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, fd.fd, 0);
check(ptr1, "mmap");
new (ptr1) Data;
// Qt
auto ptr2 = shmFile.map(0, sizeof(Data));
Data::compare(ptr1, ptr2);
}
我们需要用于C API的RAII包装器:
struct noncopyable { Q_DISABLE_COPY(noncopyable) noncopyable() {} };
struct ShmId : noncopyable {
int id;
ShmId(int id) : id{id} {}
~ShmId() { if (id != -1) shmctl(id, IPC_RMID, NULL); }
};
struct ShmPtr : noncopyable {
void * ptr;
ShmPtr(void * ptr) : ptr{ptr} {}
~ShmPtr() { if (ptr != (void*)-1) shmdt(ptr); }
};
struct Handle : noncopyable {
int fd;
Handle(int fd) : fd{fd} {}
~Handle() { if (fd != -1) close(fd); }
};
下面介绍如何在C和Qt之间互操作SYSV共享内存部分。不幸的是,除非您在C中重新实现qHash
,否则不可能:
void ipc_shm_test() {
QTemporaryFile shmFile;
check(shmFile.open(), shmFile, "shmFile.open");
// SYSV SHM
auto nativeKey = QFile::encodeName(shmFile.fileName());
auto key = ftok(nativeKey.constData(), qHash(nativeKey, 'Q'));
check(key, "ftok");
ShmId id{shmget(key, sizeof(Data), IPC_CREAT | 0600)};
check(id.id, "shmget");
ShmPtr ptr1{shmat(id.id, NULL, 0)};
check(ptr1.ptr, "shmat");
new (ptr1.ptr) Data;
// Qt
QSharedMemory shm;
shm.setNativeKey(shmFile.fileName());
check(shm.attach(QSharedMemory::ReadOnly), shm, "shm.attach");
auto ptr2 = shm.constData();
Data::compare(ptr1.ptr, ptr2);
}
以下是如何互操作内存映射文件:
// https://github.com/KubaO/stackoverflown/tree/master/questions/sharedmem-interop-39573295
#include <QtCore>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <cerrno>
#include <stdexcept>
#include <string>
void mmap_test() {
QTemporaryFile shmFile;
check(shmFile.open(), "shmFile.open");
shmFile.write({sizeof(Data), 0});
check(true, shmFile, "shmFile.write");
check(shmFile.flush(), shmFile, "shmFile.flush");
// SYSV MMAP
Handle fd{open(QFile::encodeName(shmFile.fileName()), O_RDWR)};
check(fd.fd, "open");
auto ptr1 = mmap(NULL, sizeof(Data), PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, fd.fd, 0);
check(ptr1, "mmap");
new (ptr1) Data;
// Qt
auto ptr2 = shmFile.map(0, sizeof(Data));
Data::compare(ptr1, ptr2);
}
最后,测试线束:
int main() {
try {
ipc_shm_test();
mmap_test();
}
catch (const std::runtime_error & e) {
qWarning() << e.what();
return 1;
}
return 0;
}
intmain(){
试一试{
ipc_shm_测试();
mmap_测试();
}
捕获(const std::runtime_error&e){
qWarning()可能是您正在搜索的内容