C 进程间共享内存和pthread_屏障:如何确保安全?

C 进程间共享内存和pthread_屏障:如何确保安全?,c,synchronization,pthreads,mmap,C,Synchronization,Pthreads,Mmap,我想要一个简单的进程间障碍解决方案。这里有一个解决方案: 但我完全迷恋mmap。。。在我的第一次尝试中,它失败了十分之一(segfault或deadlock) 我知道我的问题来自同步问题,但我找不到它。我找到了一个设置mmaped memory()的示例,但我不确定它是否适合mmaped pthread_屏障 下面是我的代码摘录: #define MMAP_FILE "/tmp/mmapped_bigdft.bin" void init_barrier() { pthread_barrie

我想要一个简单的进程间障碍解决方案。这里有一个解决方案:

但我完全迷恋mmap。。。在我的第一次尝试中,它失败了十分之一(segfault或deadlock)

我知道我的问题来自同步问题,但我找不到它。我找到了一个设置mmaped memory()的示例,但我不确定它是否适合mmaped pthread_屏障

下面是我的代码摘录:

#define MMAP_FILE "/tmp/mmapped_bigdft.bin"

void init_barrier() {
  pthread_barrier_t *shared_mem_barrier;
  pthread_barrierattr_t barattr;
  pthread_barrierattr_setpshared(&barattr, PTHREAD_PROCESS_SHARED);

  hbcast_fd = open(MMAP_FILE, O_RDWR | O_CREAT | O_TRUNC, (mode_t)0600);
  result = lseek(hbcast_fd, sizeof(pthread_barrier_t)-1, SEEK_SET);
  result = write(hbcast_fd, "", 1);
  shared_mem_barrier = (pthread_barrier_t*) mmap(0, sizeof(pthread_barrier_t), PROT_READ | PROT_WRITE, MAP_SHARED, hbcast_fd, 0);
  if (mpi_rank == 0) {
    int err = pthread_barrier_init(shared_mem_barrier, &barattr, host_size);
  }
  MPI_Barrier(some_communicator);
}
问题:

  • mmap初始化中是否遗漏了某些内容
  • 哪些操作应由所有流程执行,哪些操作应由一个流程执行
新问题

管理pthread屏障哪个更安全?还是基于相同的机制

  • shmget
  • shm_开放
  • mmap
  • 另一个

您不希望在每个进程中都使用O_TRUNC打开文件。每次执行此操作时,都会再次截断文件,并可能使以前执行的mmap操作无效(更改文件大小时对以前的mmap的影响通常未定义)

除此之外,我不认为你可以在mmap的内存中有一个信号量,并让它正常工作(它可能在某些操作系统平台上,所以我怀疑它是否能保证按照你想要的方式工作)


您真正想要使用的是共享内存。在“shmget”和“shmat”上学习如何创建和映射共享内存。您可能仍然需要一个文件来传递共享内存ID,在应用程序崩溃期间,您应该通过注册信号处理程序来释放共享内存ID。否则,您可能会留下僵尸共享内存分配,并超出您的操作系统资源限制。当您尝试在主线程上创建共享内存段时,如果使用ENOSPC,您就会知道发生了这种情况。

正如Charles所提到的,截断似乎就是您的原因。此外,应该使用pthread_barrieratr_init初始化属性

至于另一个问题,只有一个进程应该进行初始化,然后所有进程都应该调用pthread_barrier_wait(就像MPI一样)

我看到了你的另一个问题,所以我知道你为什么不想使用MPI。因此,您可能只需要执行一个MPI屏障来初始化pthread屏障,如下所示:

if (rank == 0)
{
  /* Create the shared memory segment, initialise the barrier. */
}
MPI_Barrier(communicator);
if (rank != 0)
{
  /* Load the shared memory segment, cast it to a pthread_barrier_t* and store.
   * It's already initialised */
}

您应该使用
shm_open
创建共享段

  • 使用参数
    O_create
    you 应该能够检测到进程 是第一个创建段的
  • 只有这一过程才应该成为现实 将线段映射到适当的长度 并初始化屏障
  • 所有其他发现他们 是不是第一个应该睡一觉 然而,一秒钟左右就足够了,然后映射段
  • 在此之后,所有流程都可以 障碍物的同步化

您会使用哪种共享内存方法?上次我需要执行进程间屏障时,我使用了MPI;)POSIX共享内存应该很好,这是您已经在使用的。在正确初始化共享内存之前,您只需停止其他进程访问共享内存。我的问题是,对于pthread_屏障,我应该使用哪个共享内存范例:mmap、shmget,另一个?抱歉,没有正确读取初始代码。我会用shm_open。你有没有一个指针来解释这些?您说过mmap不是pthread_屏障的最佳选择。shmget更好吗?你还有别的打算吗?