我正在寻找有关是否正确执行以下操作的反馈。我正在移植一些大量使用命名互斥量的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))
}
答案 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
本身就不足以确保正确的同步-您仍需要使用某种原子增量/减量或原子比较和交换。