我想编写一些函数void* share(void*, int)
,它应设置共享内存以在指针处共享数据。
我的第一次尝试看起来像(没有支票等):
void* share(void *toBeShared, int size) {
int fd = shm_open(SHM_NAME, O_CREAT | O_RDWR | O_EXCL, S_IRUSR | S_IWUSR);
ftruncate(fd, size);
return mmap(toBeShared, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
}
但这似乎并不像我希望的那样有效。第二次尝试是这样的:
void* share(void *toBeShared, int size) {
void *mem = NULL;
int fd = shm_open(SHM_NAME, O_CREAT | O_RDWR | O_EXCL, S_IRUSR | S_IWUSR);
ftruncate(fd, size);
mem = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)
memcpy(mem, toBeShared, size);
return mem;
}
这确实有效,但我需要复制整个数据,我想避免这些。
因此我的问题是:有没有办法分享已经分配的内存(如果可能的话,无需复制太多),如果可以的话,怎么办呢?
提前致谢。
PS:我已经看到了更多这些问题(例如here和here),但没有给出答案。
我想如何使用它:
typedef struct {
char *name;
int status;
} MyTask;
int main(int argc, char** argv) {
MyTask* taskList = NULL, sharedTaskList = NULL;
int length = 0;
...
readFile(&taskList, &length, ...);
sharedTaskList = share(taskList, length * sizeof(MyTask));
// or maybe even better: without needing to assign it to new variable
for(i = 0; i < NR_WORKERS; i++) {
switch(pid = fork()) {
//etc...
}
}
...
return 0;
}
答案 0 :(得分:-4)
如何共享现有内存?
不要共享现有内存。获取一些(少量)“新鲜”共享内存并稍后使用(即填写或读取)。
假设您使用的是Linux,请阅读shm_overview(7)。
我猜你的一些功能可能会失败。您应该针对每次通话失败进行测试,例如
int fd = shm_open(SHM_NAME, O_CREAT | O_RDWR | O_EXCL, S_IRUSR | S_IWUSR);
if (fd<0) {perror("shm_open"); exit(EXIT_FAILURE);};
等等。也许还可以使用strace(1)
有没有办法分享已经分配的内存
简短回答,不!(或者不容易,而不是以便携方式)。你通常会做相反的事情:获得一些已知大小的共享段,并使用一些指针。 (相同的共享段可能在不同的进程中具有不同的虚拟地址,例如由于ASLR)。
您可以在某些已使用的虚拟地址空间子网段上使用mmap(2)和MAP_FIXED
(用新的覆盖&替换映射,而不是共享< em>现有的映射!),但我建议避免这种情况。请注意,虚拟地址空间是以页面的倍数进行管理的,因此无法共享某些非页面对齐的数据。因此,除非share
和toBeShared
页面对齐,否则size
函数不可能。您可以考虑特定于Linux的mremap(2)
换句话说,您的应用程序应首先分配一些共享内存,然后在获取的共享段内放置/使用一些数据,而不是尝试共享一些现有的非共享虚拟内存范围。所以你可能想要编写一些void* get_my_shared_memory();
代码(假设大小是一个编译时常量,并且每个进程调用一次该函数,并且它产生的虚拟地址通常会因进程而异)
实际上,内存是一种有限的资源,共享内存是一种稀缺且非常有限的资源。在大多数系统上,你只能分享几十兆字节...所以共享任意大量的内存是不合理的。
也许您的整个应用程序可能只使用某个服务器,例如一些数据库服务器àlaPostGreSQL,通过向该服务器发出请求(以及使用DBMS的ACID属性)来共享信息。或者,您可以将其组织为一个监视进程,用于交换消息(例如,要处理的URL) - 在管道或套接字或fifos-与从属进程。但是我们不知道你在编写什么样的应用程序。
BTW,共享内存是不够的。 您需要同步您的流程。