用O_CREAT打开 - 是打开还是创建?

时间:2013-04-03 21:26:45

标签: c file unix

我有10个进程尝试使用open(O_CREAT)调用同时或多或少地打开同一个文件,然后删除它。是否有任何可靠的方法来确定哪个进程实际创建了文件,哪个进程已经打开已创建文件,例如,如果我想准确计算在这种情况下打开该文件的次数。

我想我可以在文件打开操作上放置一个全局互斥,并使用O_CREAT和O_EXCL标志执行一系列open()调用,但这不符合我对“robust”的定义。

2 个答案:

答案 0 :(得分:6)

O_EXCL标记与O_CREAT一起使用。如果文件存在且errno将设置为EEXIST,则会失败。如果确实失败了 然后在没有O_CREAT且没有O_EXCL模式的情况下再次尝试打开。

e.g。

int fd = open(path, O_WRONLY | O_CREAT | O_EXCL, 0644);
if ((fd == -1) && (EEXIST == errno))
{
    /* open the existing file with write flag */
    fd = open(path, O_WRONLY);
}

答案 1 :(得分:3)

大致基于您的评论,您需要与此功能类似的内容:

/* return the fd or negative on error (check errno);
   how is 1 if created, or 0 if opened */
int create_or_open (const char *path, int create_flags, int open_flags,
                    int *how) {
    int fd;
    create_flags |= (O_CREAT|O_EXCL);
    open_flags &= ~(O_CREAT|O_EXCL);
    for (;;) {
        *how = 1;
        fd = open(path, create_flags);
        if (fd >= 0) break;
        if (errno != EEXIST) break;
        *how = 0;
        fd = open(path, open_flags);
        if (fd >= 0) break;
        if (errno != ENOENT) break;
    }
    return fd;
}

此解决方案不是防弹。可能有些情况(可能是符号链接?)会导致它永远循环。此外,它可能会锁定某些并发方案。我会留下解决这些问题作为练习。 : - )


在您编辑的问题中,您提出:

  

我有10个进程尝试使用open(O_CREAT)调用同时或多或少地打开同一个文件,然后将其删除。

一个hack-ish,但更具防弹性的解决方案是为每个进程提供不同的用户ID。然后,只需使用常规的open(path, O_CREAT|...)电话。然后,您可以在文件描述符上使用fstat()查询文件,并检查st_uid结构的stat字段。如果该字段等于进程的用户ID,那么它就是创建者。否则,这是一个开场白。这是有效的,因为每个进程在打开后都会删除该文件。