簡體   English   中英

安全地初始化共享內存

[英]Initializing shared memory safely

我有幾個進程通過OS X上的POSIX共享內存相互通信。我的問題是這些進程可能以任何順序生成,並嘗試同時初始化共享內存段。

我嘗試將咨詢鎖與fcntlflock一起使用,但都無法告訴我我傳遞了無效的文件描述符(我肯定文件描述符不是無效的)。 顯然,這是不可能的。

有其他選擇嗎? 還是有我不知道的有關對共享內存使用鎖的任何詳細信息?

編輯:我嘗試使用鎖看起來像這樣:

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

一種常見的技術是首先使用O_CREAT|O_EXCL調用shm_open 這僅對隨后必須進行設置的一個過程成功。 然后其他人將不得不像以前一樣進行打開操作,並稍等一會兒(可能是輪詢)安裝完成。

編輯:顯示如何如評論中所述工作。

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

我已經能夠重現該問題。 然后我在標准中發現一個可悲的發現:

當文件描述符fildes引用共享內存對象時,fcntl()的行為應與常規文件相同,不同之處在於未指定參數cmd的以下值的影響:F_SETFL,F_GETLK,F_SETLK和F_SETLKW

因此很可能尚不支持。 對於這樣一個簡單的設置,我將使用信號量來表示“內存已准備就緒”。

編輯

似乎我需要提及的是可以使用“ O_EXCL”創建信號量(因此不存在種族)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM