首页 > 解决方案 > 进程之间共享的互斥锁不起作用

问题描述

我正在尝试在进程之间创建一个简单的共享互斥锁。这个想法是我将运行相同的可执行文件两次以创建两个进程,第一个进程应该创建一个共享互斥锁并将其锁定并休眠一段时间,同时另一个进程应该发现共享互斥锁被锁定并应该报告相同. 为此,我编写了以下代码 -

#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;
        }
    }

标签: clinuxsynchronizationpthreadsmutex

解决方案


感谢@Shawn 指出首先检查共享内存是否存在。检查共享内存对象是否已经存在,如果存在则不再初始化互斥锁。总结是如果我们重新初始化一个互斥锁,那么它的锁信息就会被覆盖,因此它不起作用。

    mutex_id = shm_open(MYMUTEX, O_CREAT | O_RDWR | O_EXCL, mode);
    if (mutex_id < 0) {
        mutex_id = shm_open(MYMUTEX, O_RDWR, mode);
        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;
        }
    } else {
        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;
        }
        pthread_mutexattr_t mattr;
        pthread_mutexattr_init(&mattr);
        pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED);
        pthread_mutex_init(mutex, &mattr);
        pthread_mutexattr_destroy(&mattr);
    }
    printf("Mutex Id : %d\n", mutex_id);
    printf("Mutex : %p\n", mutex);

    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);
    }

控制台 1

[gbose@seadev:~/mutlti-threaded-client-server$]./mutex
Mutex Id : 3
Mutex : 0x7f3cd591c000
Acquired Lock now sleeping...

控制台 2

[gbose@seadev2:~/mutlti-threaded-client-server$]./mutex
Mutex Id : 3
Mutex : 0x7f09db159000
Cannot acquire Lock. Some instance might be already running


推荐阅读