Mr *_*der 6 c posix shared-memory
我想编写一些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);
}
Run Code Online (Sandbox Code Playgroud)
但这似乎并不像我想的那样有用.第二次尝试是这样的:
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;
}
Run Code Online (Sandbox Code Playgroud)
这确实有效,但我需要复制整个数据,我想避免.
因此我的问题是:有没有办法分享已经分配的内存(如果可能的话,无需复制太多),如果可以的话,怎么办呢?
提前致谢.
PS:我已经看到了更多这些问题(例如这里和这里),但那里没有给出答案.
我想怎么用它:
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;
}
Run Code Online (Sandbox Code Playgroud)
Bas*_*tch -4
\n\n\n如何共享现有内存?
\n
不要共享现有内存。获取一些(少量)“新鲜”共享内存并稍后使用(即填充或读取)它。
\n\n假设您使用的是 Linux,请阅读shm_overview(7)。
\n\n我猜你的某些功能可能会失败。您应该测试每次调用是否失败,例如
\n\nint fd = shm_open(SHM_NAME, O_CREAT | O_RDWR | O_EXCL, S_IRUSR | S_IWUSR);\nif (fd<0) {perror("shm_open"); exit(EXIT_FAILURE);};\n
Run Code Online (Sandbox Code Playgroud)\n\n等等。也许还可以使用strace(1)
\n\n\n\n\n有没有办法共享已经分配的内存
\n
简短的回答,不!(或者不容易,并且不是以便携的方式)。通常,您会执行相反的操作:获取一些已知大小的共享段,并使用一些指针进入其中。(同一共享段在不同进程中可能有不同的虚拟地址,例如由于ASLR)。
\n\n您可以将mmap(2)与MAP_FIXED
某些已使用的虚拟地址空间子段一起使用(这将覆盖并用新的映射替换映射,而不是共享现有映射!),但我建议避免这种情况。请注意,虚拟地址空间是在多个页面中管理的,因此无法共享一些未页面对齐的数据。因此,除非和都是页面对齐的share
,否则您的功能是不可能的。您可以考虑 Linux 特定的mremap(2)toBeShared
size
换句话说,您的应用程序应该首先分配一些共享内存,然后在获得的共享段中放置/使用一些数据,而不是尝试共享一些现有的非共享虚拟内存范围。因此,您可能想要编写一些代码void* get_my_shared_memory();
(假设大小是编译时常量,并且每个进程调用该函数一次,并且其生成的虚拟地址通常会因进程而异)
在实践中,内存是一种有限的资源,而共享内存是一种稀缺且非常有限的资源。在大多数系统上,您只能共享几十兆字节......因此共享任意大量的内存是不合理的。
\n\n也许您的整个应用程序可能只使用某些服务器,例如某些数据库服务器 \xc3\xa0 la PostGreSQL ,通过向该服务器发出请求(并使用DBMS 的ACID属性)来共享信息。或者您可以将其组织为一个监视进程,在管道、套接字或 fifos 上与从属进程交换消息(例如要处理的 URL)。但我们不知道您正在编写什么样的应用程序。
\n\n顺便说一句,共享内存是不够的。您需要同步您的流程。
\n