我可以使用初始化程序初始化静态内存中的互斥锁:
pthread_mutex_t mymutex = PTHREAD_MUTEX_INITIALIZER;
但是如何在共享内存中初始化一个,我必须分别分配内存而不是初始化变量?我可以做一个memcpy()吗?
pthread_mutex_t mymutex = PTHREAD_MUTEX_INITIALIZER;
memcpy(&globalmutex, &mymutex, sizeof(mymutex);
我以为我记得很久以前读过这样一来,当将一个互斥锁分配到内存保证初始化为零时,它不需要初始化 - 仅用于这种情况 - 但我找不到写下来任何地方。这是真的吗? - 我注意到我的redhat系统上PTHREAD_MUTEX_INITIALIZER被定义为{{0,0,0,0,0,0,{0,0}}}。
答案 0 :(得分:4)
这里需要小心,并非所有实现都支持可以跨进程工作的互斥锁。
PThreads本身通过使用进程共享属性来支持此功能,但是,如果您需要,则不会使用默认初始化程序。
相反,在正确构建互斥锁属性结构之后,您需要使用pthread_mutex_init()
:
int pthread_mutex_init(
pthread_mutex_t *mutex,
const pthread_mutexattr_t *attr);
最好的办法是在共享内存中分配空间然后将其转换为正确的类型并将其传递给init
函数。我认为这可能比在初始化后复制它更安全。
答案 1 :(得分:1)
我遇到了类似的问题,我使用的一种方法是尝试使用(O_CREAT | O_RDWR | O_EXCL)
专门创建共享内存。如果创建成功,则在共享内存中初始化互斥锁。如果失败,请检查共享内存是否已存在。如果存在共享内存,只需使用标志O_RDWR
打开它并映射到您的互斥锁,但假设它已由成功创建它的进程初始化。这里有一些伪代码(POSIX + pthreads):
/* semaphore POST (block access from other processes) */
/* try to exclusively create */
int fd = shm_open (name, (O_CREAT | O_RDWR | O_EXCL), (S_IRUSR | S_IWUSR));
if (fd == -1) {
/* failed creation */
/* semaphore WAIT (wait until mutex initialized) */
if (errno == EEXIST) {
/* already exists, try to open */
fd = shm_open (name, O_RDWR, (S_IRUSR | S_IWUSR));
if (fd == -1) {
/* check errors */
} else {
/* optionally check shared data size with fstat */
fstat () ...
/* map */
mmap () ...
}
} else {
/* check create errors */
}
} else {
/* successful creation! */
/* truncate */
ftruncate () ...
/* map */
mmap () ...
/* initialize mutex */
pthread_mutexattr_init () ...
pthread_mutexattr_setpshared ( ... , PTHREAD_PROCESS_SHARED ) ...
pthread_mutex_init () ...
/* semaphore WAIT (wait until all processes are finished) */
}
此方法的一个问题是可能存在竞争条件,其中另一个进程打开它并尝试在创建共享内存之后但在初始化互斥锁之前立即锁定互斥锁。我从未试图测试这种情况(很难实现) - 我没有使用推动这种限制的系统。但是,在这种情况下,信号量可能会有助于阻止访问,直到创建互斥锁。我在评论中添加了信号量逻辑,但我很感激它的反馈(信号量没有实现或测试)。
经过一番思考,我意识到IPC信号量保护可能更好作为互斥体,然后我们必须递归地创建共享内存互斥量哈哈。但严重的是,只有一个单独管理保护互斥锁的创建,初始化和销毁的进程才能正常工作。