【问题标题】:shared memory mutex with struct pointers带有结构指针的共享内存互斥锁
【发布时间】:2019-03-21 17:42:26
【问题描述】:

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

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

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

}

【问题讨论】:

  • 我已经读过这个,还有系统 V 信号量,但我也看到这篇文章建议互斥体更好stackoverflow.com/questions/6477525/…
  • 请编辑您的问题并修正缩进。
  • @Someprogrammerdude 进程共享互斥锁是一种宝贵的资源。一大优势是(至少在 linux 上)使用pthread_mutex_t,在无争议的情况下,不需要系统调用来锁定或解锁。如果您需要,这是一个巨大的性能胜利。
  • 更正我的评论(关于性能优势):我只是查看了 glibc 源代码,并且(如果我没看错的话)似乎sem_open 和 linux 上的朋友也应该能够在没有无争用情况下的系统调用。
  • @Someprogrammerdude:PTHREAD_PROCESS_SHARED 标志的目的是为进程间锁定初始化一个互斥锁。这没有什么问题。

标签: c pthreads mutex shared-memory


【解决方案1】:

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

我不明白的一件事是struct GenQ 部分。 volatile 关键字暗示此结构已经驻留在共享内存中。但是,如果它在共享内存中,那么您存放在那里的互斥指针在创建它的进程之外将无效。互斥体本身可能驻留在共享内存中,其他进程也可能有指向互斥体的指针,但共享内存区域在其虚拟地址空间内的确切位置可能不同,因此它们的指针值也会不同(因此指针应该是进程私有的)。

如果GenQ 结构已经在共享内存中,为什么不简单地声明一个pthread_mutex_t不是指针——实际互斥体的空间)在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 本身不足以确保正确同步——您仍然需要使用某种原子增量/减量或原子比较和交换。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-12
    • 2013-11-24
    • 2021-10-10
    相关资源
    最近更新 更多