关于stackoverflow,是否可以在进程之间共享pthread互斥锁有很多问题,但是我没有发现有关共享互斥锁初始化的问题/答案。
据我了解,使用进程共享互斥锁的常见方法如下:分配共享内存块,在共享内存块上初始化pthread互斥锁,然后使用它。
在创建共享内存的情况下,如果多个进程尝试分配具有相同密钥ID的共享内存块,则由OS处理。好的,但是我不明白的是如何安全地在共享内存块上初始化互斥锁?
我对吗,pthread_mutex_init不提供任何安全的方法来从不同进程中同时初始化pthread_mutex_t?如果是,我如何为进程提供独占访问权限以初始化共享的"互斥"?以及如何确定另一个进程是否成功初始化了互斥锁?
第二个问题涉及阻止互斥锁的进程崩溃的情况。好了,有一个健壮的互斥锁可以处理这种情况并返回相应的错误代码。共享内存块呢?似乎一个进程应该注意是否是最后一个使用共享内存破坏它的进程。
出于好奇,为什么不使用POSIX信号量呢? man7.org/linux/man-pages/man7/sem_overview.7.html与pthread_mutex不同,POSIX信号量用于进程间通信。
@jameslarge这是一个好问题。 有些人建议使用互斥锁而不是信号灯。 例如,stackoverflow.com / q / 6477525/465662我试图找到任何真正的优势
我对吗,pthread_mutex_init不提供任何安全的方法来从不同进程中同时初始化pthread_mutex_t?
正确。您可以确保只有一个进程在互斥锁上调用pthread_mutex_init(),并且在该调用成功返回之前,没有进程尝试对该互斥锁进行操作。
例如,使用POSIX shm_open()共享内存区域,您可以让进程尝试使用O_CREAT和O_EXCL标志打开该区域,以便恰好有一个进程可以成功创建它。然后,此过程负责调整共享内存区域的大小并使用pthread_mutex_init()初始化互斥量。然后,其他进程必须在打开共享内存区域之前等待初始化过程中的某种通知-例如,您可以让进程阻止打开FIFO O_RDONLY,并让初始化过程通过打开FIFO O_WRONLY通知它们。 (这将导致开放成功)。
通常,共享内存段将不是进程之间的唯一通信通道。通常,您将引导通过UNIX域套接字的通信,并协商在其上的共享内存区域的设置,甚至可能会通过SCM_RIGHTS消息通过该套接字传递共享内存区域文件描述符。然后,共享内存区域将用于加速对性能敏感的IPC。
不能使用pthread_once(3)安全地完成初始化吗? 我知道可以为给定进程的线程服务。 假设after_control变量也位于共享内存中,它将跨进程工作吗?
@kaiwan:POSIX仅表示pthread_once()在同一进程的线程之间起作用。 它确实说pthread_once_t变量必须静态初始化,这是将其放置在共享内存区域中的问题。
我使用mmap创建共享内存块。
int fd = open(filename, O_RDWR | O_CLOEXEC);
当文件不存在时,则fd < 0,然后尝试初始化互斥锁内存。
fd = open(filename, O_RDWR | O_CREAT | O_CLOEXEC | O_TRUNC | O_EXCL,
S_IRUSR);
if(fd < 0) {
// two processes might try to create the file simultaneously.
// one open is success, the other one fail because of O_EXCL.
sleep_random_10ms();
continue; // continue and try again.
}
注意:由于S_IRUSR,open成功执行并创建文件后,该文件仍不可写。其他任何进程将无法使用O_RDWR打开文件,因此第一个open仍然会失败。初始化互斥锁时,没有进程将使用互斥锁。
创建文件后,我们照常初始化互斥锁
pthread_mutexattr_init(&att);
pthread_mutexattr_setrobust(&att);
pthread_mutexattr_setpshared(&att, PTHREAD_PROCESS_SHARED);
pthread_mutex_init(&mutex, &att)
write(fd, &mutex, sizeof(mutex))
fchmod(fd, S_IRUSR | S_IWUSR)
fclose(fd);
最后两个步骤使文件可写,以便任何其他进程将在第一次尝试时成功打开文件。
我们开始照常使用互斥锁
mutex = (pthread_mutex_t*) mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE, MAP_SHARED, fd_, 0);
pthread_mutex_lock(mutex);
....
pthread_mutex_unlock(mutex);
清理
munmap(&mutex);
close(fd);