eth*_*ice 5 c c++ linux mmap shared-memory
从shm_open手册页:
新的共享内存对象最初的长度为零.可以使用ftruncate(2)设置对象的大小.[...] shm_open()函数本身不会创建指定大小的共享对象,因为这样做会复制现有函数,该函数设置文件描述符引用的对象的大小.
这不会使应用程序暴露于竞争条件吗?考虑以下伪代码:
int fd = shm_open("/foo", CREATE);
if ( fd is valid ) {
// created shm object, so set its size
ftruncate(fd, 128);
} else {
fd = shm_open("/foo", GET_EXISTING);
}
void* mem = mmap(fd, 128);
Run Code Online (Sandbox Code Playgroud)
由于shm_open和ftruncate调用(一起)不是原子的,你可能有一个竞争条件,一个进程调用shm_open(CREATEcase),但是在调用之前ftruncate,另一个进程调用shm_open(GET_EXISTINGcase)并尝试mmap0大小的对象,甚至可能写入它.
我可以想到两种避免这种竞争条件的方法:
使用IPC互斥量/信号量使整个事物同步,或者......
如果它是安全的(按POSIX),请ftruncate同时调用CREATE和GET_EXISTING案例.
哪种方法可以避免这种竞争条件?
您的方法(ftruncate从两者调用)应该可以工作,但是您需要一种方法来同步使用共享内存段的内容.由于内存最初是空的(零填充),因此不包含有效的同步对象,除非您要使用atomics自行滚动,否则无论如何都需要辅助形式的同步来控制对共享内存的访问.
我认为通常情况下,您不希望多个流程竞争创建或打开具有固定名称的共享内存段,您希望拥有一个负责创建具有随机名称的段的所有者进程,O_EXCL以避免随机或恶意冲突,然后传递名称,一旦您成功打开它,调整它的大小,并在其中创建同步对象,到其他需要访问它的进程.