安全初始化共享内存 [英] Initializing shared memory safely

查看:269
本文介绍了安全初始化共享内存的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有几个流程,每个通过POSIX共享内存在OS X通信
我的问题是这些过程可以以任意顺序产卵,并试图在同一时间进行初始化共享内存段。

我试着用咨询锁与的fcntl 羊群,但均不能告诉我,我传递一个无效的文件描述符(我敢肯定的文件描述符是不是无效)。所以很明显这是出来的图片。

是否有替代品吗?或者是有关于使用共享内存锁,我是不知道的任何细节?

编辑:
我在使用锁的尝试看起来是这样的:

  //一些声明...结构队列{
    INT指数[ENTRIES_PER_QUEUE]
    sem_t锁;
    sem_t readWait;
    sem_t writeSem;
    结构进入插槽[ENTRIES_PER_QUEUE]
};结构ipc_t {
    INT的fd;
    字符名称[512];
    结构队列*队列中;
};ipc_t ipc_create(为const char *名称,INT所有者){    INT isInited = 1;
    结构队列*队列中;
    struct flock的锁= {
        .l_type = F_WRLCK,
        .l_whence = SEEK_SET,
        .l_start = 0,
        .l_len = 0
    };    ipc_t康恩=的malloc(sizeof的(结构ipc_t));    sprintf的(conn->的名字,/ arqvenger_%S,名);    conn-> FD =的shm_open(conn->的名字,O_CREAT | O_RDWR,0666);
    如果(conn-> FD == -1){
        免费(康涅狄格州);
        PERROR(的shm_open失败);
        返回NULL;
    }    如果(的fcntl(conn-> FD,F_SETLKW,&安培;锁定)== -1){
        PERROR(喝醉......);
    }//做的东西与锁和放大器;释放

我得到的输出是:

 重挫...:坏的文件描述符


解决方案

一个常用的方法是先调用的shm_open O_CREAT | O_EXCL 。这将只为一个过程,那么所要做的设置成功。然后,其他人会做开放和以前一样,等待了一下,大概投票,即设置完成。

编辑::要说明如何在评论中讨论这可能是工作

 结构头{
 无符号的挥发性标志;
 pthread_mutex_t MUT;
};void *的地址= 0;
/ *尝试用独家的shm_open,然后* /
如果(/ *我们创建段* /){
  地址= MMAP(东西);
  结构头* H =地址;
  调用pthread_mutex_init(安培; H-> MUT,aSharedAttr);
  调用pthread_mutex_lock(安培; H-> MUT);
  H->标志= 1;
  / *做初始化的其余部分,然后* /
  调用pthread_mutex_unlock(安培; H-> MUT);
}其他{
  / *重试的shm_open没有排他性,然后* /
  地址= MMAP(东西);
  结构头* H =地址;
  / * initialy标志被保证是0 * /
  / *这将退出循环何时会有新值写入标志* /
  而(H-GT&;!标记)SCHED_YIELD();
  调用pthread_mutex_lock(安培; H-> MUT);
  调用pthread_mutex_unlock(安培; H-> MUT);
}

I have several processes communicating with each through POSIX shared memory on OS X. My issue is these processes could spawn in any order, and try to initialize the shared memory segment at the same time.

I tried using advisory locks with fcntl and flock but both fail telling me I'm passing an invalid file descriptor (I'm positive the file descriptor is not invalid). So clearly that's out of the picture.

Are there any alternatives to this? Or is there any details about using locks with shared memory that I'm not aware of?

Edit: My attempt at using locks looks like this:

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

The output I get is:

Tanked...: Bad file descriptor

解决方案

A common technique is to first call shm_open with O_CREAT|O_EXCL. This will succeed for only one process that then has to do the setup. The others then would have to do the open as before and wait a bit, probably polling, that the setup is finished.

Edit: To show how this could work as discussed in the comments.

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

这篇关于安全初始化共享内存的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆