关于是否可以在进程之间共享pthread互斥锁,stackoverflow上有很多问题,但我没有发现有关共享互斥锁初始化的问题/答案。
据我所知,使用进程共享互斥锁的常用方法如下:分配共享内存块,在共享内存块上初始化pthread互斥锁,使用它。
如果共享内存创建,如果多个进程尝试分配具有相同密钥ID的共享内存块,则由OS处理。好的,但我不明白的是如何安全地在共享内存块上初始化互斥锁?
我是否正确pthread_mutex_init没有提供任何安全方法来同时从不同进程初始化pthread_mutex_t?如果是,我如何为流程提供独占访问权限以初始化共享"互斥"?如何确定其他进程是否成功初始化了互斥锁?
第二个问题涉及阻止互斥锁的进程崩溃的情况。好的,有一个强大的互斥锁处理这种情况并返回相应的错误代码。共享内存块怎么样?似乎一个进程应该注意它是否是使用共享内存来破坏它的最后一个进程。
答案 0 :(得分:3)
我是否正确,pthread_mutex_init没有提供任何安全方法来同时从不同进程初始化pthread_mutex_t?
正确。您可以确保只有一个进程在互斥锁上调用pthread_mutex_init()
,并且在该调用成功返回之前,没有进程尝试在互斥锁上运行。
例如,对于POSIX shm_open()
共享内存区域,您可以让进程尝试使用O_CREAT
和O_EXCL
标志打开该区域,这样只需要一个进程成功创造它。然后,此过程负责调整共享内存区域的大小并使用pthread_mutex_init()
初始化互斥锁。然后,其他进程必须在打开共享内存区域之前等待初始化过程中的某种通知 - 例如,您可以让进程阻止打开FIFO O_RDONLY
,并让初始化过程通过打开FIFO来通知它们{ {1}}(这会导致开放成功)。
通常,共享内存段不是进程之间唯一的通信通道。通常,您将通过UNIX域套接字引导通信,并通过它协商共享内存区域的设置,甚至可能通过带有O_WRONLY
消息的套接字传递共享内存区域文件描述符。然后,共享内存区域将用于加速性能敏感的IPC。
答案 1 :(得分:0)
我使用[ec2-user@xxxx ~]$ psql -h localhost -p 5439 -U admin pgbouncer
psql: ERROR: not allowed
ERROR: not allowed
[ec2-user@xxxx pgbouncer]$ psql -h xxxxxxxx.us-east-2.redshift.amazonaws.com -p 5439 -U admin pgbouncer
Password for user admin:
psql: FATAL: database "pgbouncer" does not exist
创建一个共享内存块。
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);