繁体   English   中英

shm_open和ftruncate竞争条件可能吗?

[英]shm_open and ftruncate race condition possible?

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);

由于shm_openftruncate调用(一起)不是原子的,你可能有一个竞争条件,一个进程调用shm_openCREATE case)但是,在调用ftruncate之前,另一个进程调用shm_openGET_EXISTING case)并尝试mmap对象为0大小,甚至可能写入它。

我可以想到两种避免这种竞争条件的方法:

  1. 使用IPC互斥量/信号量使整个事物同步,或者......

  2. 如果它是安全的(按POSIX),则在CREATEGET_EXISTING情况下调用ftruncate

哪种方法可以避免这种竞争条件?

你的方法(从两者调用ftruncate )应该可行,但是你需要一种方法来同步使用共享内存段的内容 由于内存最初是空的(零填充),因此不包含有效的同步对象,除非您要使用atomics自行滚动,否则无论如何都需要辅助形式的同步来控制对共享内存的访问。

我认为通常情况下,您不希望多个流程竞争创建或打开具有固定名称的共享内存段,您希望拥有一个负责创建具有随机名称的段的所有者进程,使用O_EXCL来避免随机或恶意冲突,然后传递名称,一旦您成功打开它,将其大小,并在其中创建同步对象,到其他需要访问它的进程。

作为@R。 这里提到的另一个问题是,在创建文件之前,在内容(例如互斥锁)被初始化并准备好使用之前,仍然有一个窗口。

与上述略有不同的解决方案是:

尝试打开()。 如果open()成功,只需map()并使用必要的保证(见下文),内容已经初始化并且很好用。 如果open()失败,则创建并初始化临时文件,然后尝试将临时文件硬链接()作为所需文件,并取消链接()临时名称。

如果link()成功,我们现在已经为我们自己和其他进程提供了初始化文件。 如果link()与EEXIST失败,则另一个进程首先到达那里(与rename()不同,如果目标名称存在,则link()失败)。 无论哪种方式,我们重复的open()现在应该成功使用初始化的准备使用文件。

使用这种策略,临时文件的初始化显然存在竞争条件,但是如果初始化过程是幂等的,而不是资源过于昂贵,并且每个进程都选择一个唯一的临时文件,这是无关紧要的。 如果多个初始化可能是一个问题,则解决方案是将初始化分成两个阶段的过程,第一阶段只是文件中的互斥体,用于防止在第二阶段期间对文件的其余部分进行多次初始化。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM