我有几个进程通过OS X上的POSIX共享内存与每个进程通信。 我的问题是这些进程可以以任何顺序生成,并尝试同时初始化共享内存段。
我尝试使用fcntl
和flock
的咨询锁,但都告诉我我传递了无效的文件描述符(我肯定文件描述符无效)。很明显,这是不合适的。
有没有其他选择?或者是否有关于使用我不知道的共享内存锁的详细信息?
编辑: 我尝试使用锁是这样的:
// Some declarations...
struct Queue {
int index[ENTRIES_PER_QUEUE];
sem_t lock;
sem_t readWait;
sem_t writeSem;
struct Entry slots[ENTRIES_PER_QUEUE];
};
struct ipc_t {
int fd;
char name[512];
struct Queue* queue;
};
ipc_t ipc_create(const char* name, int owner) {
int isInited = 1;
struct Queue* queue;
struct flock lock = {
.l_type = F_WRLCK,
.l_whence = SEEK_SET,
.l_start = 0,
.l_len = 0
};
ipc_t conn = malloc(sizeof(struct ipc_t));
sprintf(conn->name, "/arqvenger_%s", name);
conn->fd = shm_open(conn->name, O_CREAT | O_RDWR, 0666);
if (conn->fd == -1) {
free(conn);
perror("shm_open failed");
return NULL;
}
if (fcntl(conn->fd, F_SETLKW, &lock) == -1) {
perror("Tanked...");
}
// Do stuff with the lock & release it
我得到的输出是:
Tanked...: Bad file descriptor
答案 0 :(得分:4)
一种常见的技巧是首先使用shm_open
来呼叫O_CREAT|O_EXCL
。只有一个进程必须进行设置才能成功。其他人则必须像以前一样打开并等待,可能是轮询,设置已完成。
修改:要显示这可以如评论中所讨论的那样发挥作用。
struct head {
unsigned volatile flag;
pthread_mutex_t mut;
};
void * addr = 0;
/* try shm_open with exclusive, and then */
if (/* we create the segment */) {
addr = mmap(something);
struct head* h = addr;
pthread_mutex_init(&h->mut, aSharedAttr);
pthread_mutex_lock(&h->mut);
h->flag = 1;
/* do the rest of the initialization, and then */
pthread_mutex_unlock(&h->mut);
} else {
/* retry shm_open without exclusive, and then */
addr = mmap(something);
struct head* h = addr;
/* initialy flag is guaranteed to be 0 */
/* this will break out of the loop whence the new value is written to flag */
while (!h->flag) sched_yield();
pthread_mutex_lock(&h->mut);
pthread_mutex_unlock(&h->mut);
}
答案 1 :(得分:3)
我能够重现这个问题。然后我在the standard发现了一个悲伤的通知:
当文件描述符fildes引用共享内存对象时, fcntl()的行为应该与普通文件的行为相同,除了 参数cmd的以下值的效果应为 未指定:F_SETFL,F_GETLK,F_SETLK和 F_SETLKW 。
所以它可能还没有得到支持。对于这样一个简单的设置,我会使用信号量来表示“内存已准备就绪”。
似乎我需要提到可以使用“O_EXCL”创建信号量(因此没有比赛)。