使用“shm_open()”在两个进程之间共享一个带有指针的结构
Sharing a struct with a pointer between two processes using `shm_open()`
我有以下结构,
typedef struct arrays {
int *array;
int max;
int min;
} array;
其中*array
指向动态分配的数组,max
和min
保存数组中的最大和最小数。
我需要在两个进程之间共享这个结构的实例(我可以在 C 中使用单词 'instance' 吗?),我是否应该首先使用 shm_open()
来分配指向的数组*array
第二个用于分配结构本身,或者是否有更好的方法来实现相同的结果?
我不知道它是否 更好 但你可以只用一次分配来做到这一点:分配一个大缓冲区以包含结构 和 数组,然后使 array
指向缓冲区 + 结构的大小。
好的,第一个答案就像你告诉医生 "It hurts when I do this" 而医生说 "then dont DO that!"
假设您打算这样做,请记住 shm_open
使一块内存可用于共享:如果您在共享的内存中有一个指向 malloc 内存的指针,它将是一个指针就另一个进程而言,到堆中的某个随机地址。您需要分配整个缓冲区,整个内存块,然后共享它。
更新
根据下面的问题,如果您想在运行时分配缓冲区,那么规范的方法是:
#define HOWBIGISMYBUFFER (3*GAZILLION)
char * buf;
if((buf = malloc(HOWBIGISMYBUFFER)) == 0){
/* make splodey noises and terminate */
}
/* now you have your buffer */
当然 GAZILLION
是在别处定义的。尽管如此,你不想那样做。您想要实现的是一个可以共享的静态内存块,并且在堆上分配它会使您暴露于各种非常难以跟踪的错误。 (考虑,例如,您在程序 A 中分配内存,将其共享给程序 B,然后程序 B 通过缓冲区溢出破坏程序 A 的堆。或者考虑,如果程序 B 在程序 A 崩溃后保持 运行 怎么办? )
您要做的是创建一个 static 缓冲区。最简单的方法是制作一个 .h
文件:
/* my_buffer.h */
char bfr[HOWBIGISMYBUFFER];
然后将其包含在您想要共享内存的任何位置。 I 会做的是写一个模块:
/* my_buffer.c */
char bfr[HOWBIGISMYBUFFER];
char * init(){ /* do your shm_open here and returna pointer to bfr */ }
你需要这样做。
- 在每个进程中使用shm_open得到一个文件描述符。您必须在每个进程中传递 shm_open 相同的 name。名称是共享内存区域与其他共享内存区域的区别。名称必须以斜杠开头:
"/somename"
.
- 使用第一步得到的文件描述符调用mmap.
- 来自
mmap
的地址 return 是您的共享内存地址。它是随机的,并且在每个过程中都是不同的。
- 因为3,你不能在共享内存区域内使用指针。您需要使用从共享内存开始的整数偏移量,或者完全取消间接寻址。例如,将整个共享内存区域视为一个整数数组。前两个单元格包含
min
和 max
,实际数字从那之后开始。
mmap
将 return 可用内存,您不需要静态或使用 malloc
. 分配任何缓冲区
我有以下结构,
typedef struct arrays {
int *array;
int max;
int min;
} array;
其中*array
指向动态分配的数组,max
和min
保存数组中的最大和最小数。
我需要在两个进程之间共享这个结构的实例(我可以在 C 中使用单词 'instance' 吗?),我是否应该首先使用 shm_open()
来分配指向的数组*array
第二个用于分配结构本身,或者是否有更好的方法来实现相同的结果?
我不知道它是否 更好 但你可以只用一次分配来做到这一点:分配一个大缓冲区以包含结构 和 数组,然后使 array
指向缓冲区 + 结构的大小。
好的,第一个答案就像你告诉医生 "It hurts when I do this" 而医生说 "then dont DO that!"
假设您打算这样做,请记住 shm_open
使一块内存可用于共享:如果您在共享的内存中有一个指向 malloc 内存的指针,它将是一个指针就另一个进程而言,到堆中的某个随机地址。您需要分配整个缓冲区,整个内存块,然后共享它。
更新
根据下面的问题,如果您想在运行时分配缓冲区,那么规范的方法是:
#define HOWBIGISMYBUFFER (3*GAZILLION)
char * buf;
if((buf = malloc(HOWBIGISMYBUFFER)) == 0){
/* make splodey noises and terminate */
}
/* now you have your buffer */
当然 GAZILLION
是在别处定义的。尽管如此,你不想那样做。您想要实现的是一个可以共享的静态内存块,并且在堆上分配它会使您暴露于各种非常难以跟踪的错误。 (考虑,例如,您在程序 A 中分配内存,将其共享给程序 B,然后程序 B 通过缓冲区溢出破坏程序 A 的堆。或者考虑,如果程序 B 在程序 A 崩溃后保持 运行 怎么办? )
您要做的是创建一个 static 缓冲区。最简单的方法是制作一个 .h
文件:
/* my_buffer.h */
char bfr[HOWBIGISMYBUFFER];
然后将其包含在您想要共享内存的任何位置。 I 会做的是写一个模块:
/* my_buffer.c */
char bfr[HOWBIGISMYBUFFER];
char * init(){ /* do your shm_open here and returna pointer to bfr */ }
你需要这样做。
- 在每个进程中使用shm_open得到一个文件描述符。您必须在每个进程中传递 shm_open 相同的 name。名称是共享内存区域与其他共享内存区域的区别。名称必须以斜杠开头:
"/somename"
. - 使用第一步得到的文件描述符调用mmap.
- 来自
mmap
的地址 return 是您的共享内存地址。它是随机的,并且在每个过程中都是不同的。 - 因为3,你不能在共享内存区域内使用指针。您需要使用从共享内存开始的整数偏移量,或者完全取消间接寻址。例如,将整个共享内存区域视为一个整数数组。前两个单元格包含
min
和max
,实际数字从那之后开始。 mmap
将 return 可用内存,您不需要静态或使用malloc
. 分配任何缓冲区