具有结构指针的共享内存互斥量

时间:2018-10-17 06:02:10

标签: c pthreads mutex shared-memory

我正在寻找有关是否正确执行以下操作的反馈。我正在移植一些大量使用命名互斥量的Windows实时代码。进行了一些搜索,但是我发现有些东西说您可以使用shm open在Linux中将共享内存用作互斥体。

我无法在此处包含所有代码,但是我将需要反馈的关键区域放在一起。我的问题是即时通讯是否设置了共享内存区域和互斥体,以及我的指针是否设置正确以及如何利用它进行锁定/解锁。

volatile struct GenQ {
    volatile pthread_mutex_t *qMutexId
    volatile sem_t  qSemId
    volatile int    nexton
    volatile int    nextoff
}

typedef struct Node{
    void                *qid
    char                shmname[80]
    sem_t               *semid
    pthread_mutex_t     *mutexID
    struct node         *next
    struct node         *prev   
}


void * init (const char *qname)
{
    struct GenQ *myq;
    char mtxstr[80];
    pthread_mutex_t *mutexQueAccess;
    int mode = S_IRWXU | S_IRWXG;
    int fd = 0;
    int status = 0;

    mtxstr[0] = "\0";
    strcpy(mtxstr,"/");
    strcat(mtxstr, qname);
    strcat(mtxstr, "_MTX");

    fd = shm_open(mtxstr, O_CREATE | O_RDWR | O_TRUNC, mode);
    if (fd == -1)
        //err handling stuff

    status = ftruncate(fd, sizeof(pthread_mutex_t));
    if(status==0){
        //err handling stuff

    mutexQueAccess = (pthread_mutex_t*) mmap(NULL, sizeof(pthread_mutex_t), 
    PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    if(mutexQueAccess == MAP_FAILED)
    //err handling stuff

    pthread_mutexattr_t mutexAttr;
    pthread_mutexattr_init(&mutexAttr);
    pthread_mutexattr_setpshared(&mutexAttr, PTHREAD_PROCESS_SHARED);
    pthread_mutex_init(mutexQueAccess, &mutexAttr);

    myq->qMutexId = mutexQueAccess;

    newNode = (Node*)malloc(sizeof(node));
    newNode->mutedID = mutexQueAccess;
    //add node to link list

}

void * openQ(*const char *qname)
{
    pthread_mutex_t *mutexQueAccess;
    int fd = 0;
    int status = 0;
    char mtxstr[80];
    int mode = S_IRWXU | S_IRWXG;

    mtxstr[0] = "\0";
    strcpy(mtxstr,"/");
    strcat(mtxstr, qname);
    strcat(mtxstr, "_MTX");

    fd = shm_open(mtxstr, O_CREATE | O_RDWR, mode);
        //check fd for err

    mutexQueAccess = (pthread_mutex_t *)mmap(NULL, sizeof(pthread_mutex_t), 
    PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
        //check for err on mmap

    newNode = (Node*)malloc(sizeof(node));
    newNode->mutedID = mutexQueAccess;
    //add node to link list


}

void * enque(const char *qname, char *msg_data)
{
    node = //search for node
    pthread_mutex_lock(&(node->mutexQueAccess))

}

1 个答案:

答案 0 :(得分:0)

在某些代码中,我正在做同样的事情,看起来很相似-部分。这个想法真的很简单。分配给互斥锁的空间大小恰好为sizeof(pthread_mutex_t)。创建共享文件,mmap并在一个过程中初始化互斥锁,然后其他人可以简单地mmap将文件设置为pthread_mutex_t *指针。

我不了解的一件事是struct GenQ部分。 volatile关键字暗示此结构已经已驻留在共享内存中。但是,如果它在共享内存中 ,则您存储在其中的互斥锁指针在创建它的过程之外无效。互斥锁本身可以驻留在共享内存中,并且其他进程也可以具有指向该互斥锁的指针,但是共享内存区域在其虚拟地址空间内的确切位置可能有所不同,因此它们的指针值也将有所不同(因此指针应该是该进程的私有对象。

因此,如果GenQ结构已经在共享内存中 了,为什么不简单地声明一个pthread_mutex_t not 指针-用于GenQ结构中的实际互斥体),然后从主进程中进行与上述代码中相同的初始化。这样,您就不需要为互斥锁使用单独的共享内存文件;它将与其他队列信息包含在相同的共享内存空间中。

另外,还考虑将PTHREAD_MUTEX_ROBUST属性(带有pthread_mutexattr_setrobust)添加到互斥锁,以便在其中一个进程在按住锁时崩溃的情况下可以恢复。

该代码如下所示:

    int err = pthread_mutex_lock(mutex_ptr);
    if (err) {
        if (err == EOWNERDEAD) {
            WARN("Mutex owner died while holding -- recovering");
            err = pthread_mutex_consistent(mutex_ptr);
            if (err)
                 FATAL("Huh?");
        } else {
            FATAL("Wha?");
        }
    }

最后,我会对您使用volatile表示怀疑。这既没有必要也不充分。如果在持有互斥锁的同时访问共享变量,则不需要volatile限定符。如果您不持有互斥锁,那么volatile本身就不足以确保正确的同步-您仍需要使用某种原子增量/减量或原子比较和交换。