【发布时间】:2021-07-28 01:28:16
【问题描述】:
我正在尝试在进程之间创建一个简单的共享互斥锁。这个想法是我将运行相同的可执行文件两次以创建两个进程,第一个进程应该创建一个共享互斥锁并将其锁定并休眠一段时间,同时另一个进程应该发现共享互斥锁被锁定并应该报告相同.为此,我编写了以下代码 -
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#define MYMUTEX "/mymutex"
int main(int argc, char* argv[])
{
pthread_cond_t *cond;
pthread_mutex_t *mutex;
int cond_id, mutex_id;
int mode = S_IRWXU | S_IRWXG;
/* mutex */
mutex_id = shm_open(MYMUTEX, O_CREAT | O_RDWR, mode);
printf("Mutex Id : %d\n", mutex_id);
if (mutex_id < 0) {
printf("shm_open failed\n");
return -1;
}
if (ftruncate(mutex_id, sizeof(pthread_mutex_t)) == -1) {
printf("ftruncate failed\n");
return -1;
}
mutex = (pthread_mutex_t *) mmap(NULL, sizeof(pthread_mutex_t), PROT_READ | PROT_WRITE, MAP_SHARED, mutex_id, 0);
if (mutex == MAP_FAILED) {
printf("mmap failed\n");
return -1;
}
printf("Mutex : %p\n", mutex);
pthread_mutexattr_t mattr;
pthread_mutexattr_init(&mattr);
pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED);
pthread_mutex_init(mutex, &mattr);
pthread_mutexattr_destroy(&mattr);
if (pthread_mutex_trylock(mutex)) {
printf("Cannot acquire Lock. Some instance might be already running\n");
} else {
printf("Acquired Lock now sleeping...\n");
sleep(25);
pthread_mutex_unlock(mutex);
pthread_mutex_destroy(mutex);
shm_unlink(MYMUTEX);
}
return 0;
}
据我所知,创建进程之间共享的互斥体,它应该映射到共享内存,并且应该设置属性 PTHREAD_PROCESS_SHARED。但是当我从两个单独的控制台运行程序时得到的结果是 -
控制台 1:
[gbose@seadev:~/mutlti-threaded-client-server$]./mutex
Mutex Id : 3
Mutex : 0x7faf2c57a000
Acquired Lock now sleeping...
控制台 2:
[gbose@seadev20:~/mutlti-threaded-client-server$]./mutex
Mutex Id : 3
Mutex : 0x7f6d5766a000
Acquired Lock now sleeping...
我在这里缺少什么?我的预感是同时初始化互斥锁是这种意外行为的根本原因 - 如果这是正确的,那么还应该做些什么来检查互斥锁是否已经初始化?
更新:处理共享内存文件已经存在的情况,根据@Shawn 的评论添加 O_EXCL 但我仍然看到 mmap() 返回的内存地址是一个新地址粘贴在控制台输出上方。
mutex_id = shm_open(MYMUTEX, O_CREAT | O_RDWR | O_EXCL, mode);
if (mutex_id < 0) {
mutex_id = shm_open(MYMUTEX, O_RDWR, mode);
} else {
if (ftruncate(mutex_id, sizeof(pthread_mutex_t)) == -1) {
printf("ftruncate failed\n");
return -1;
}
}
【问题讨论】:
-
只有一个进程应该创建共享内存并初始化互斥锁(并在最后清理)。另一个应该映射共享内存并使用互斥锁。
-
在这种情况下,计数为 1 的共享信号量更容易使用,imo。
-
@Shawn 谢谢!但是我将 shm_open 与 O_CREATE 一起使用,所以不应该自动处理如果共享内存对象已经存在然后不再创建一个的情况吗?那么 mmap 部分保持不变......如果我错了,请纠正我
-
即使共享内存存在,它也会继续重新初始化互斥体。您可以使用涉及添加
O_EXCL的逻辑,如果成功则进行初始化,如果失败则打开现有的。 -
尝试在没有
O_CREAT的情况下再次打开它。
标签: c linux synchronization pthreads mutex