我有10个进程尝试使用open(O_CREAT)调用同时或多或少地打开同一个文件,然后删除它.是否有任何可靠的方法来确定哪个进程实际上创建了文件,哪个进程已经打开已创建文件,例如,如果我想准确计算在这种情况下打开该文件的次数.
我想我可以在文件打开操作上放置一个全局互斥,并使用O_CREAT和O_EXCL标志执行一系列open()调用,但这不符合我对"robust"的定义.
使用O_EXCL
标志O_CREAT
.如果文件存在且errno将设置为,则此操作将失败EEXIST
.如果确实失败,则在没有O_CREAT
和没有O_EXCL
模式的情况下再次尝试打开
例如
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);
}
Run Code Online (Sandbox Code Playgroud)
大致根据您的评论,您想要类似于此功能的内容:
/* 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;
}
Run Code Online (Sandbox Code Playgroud)
该解决方案并非防弹。在某些情况下(可能是符号链接?)可能会导致它永远循环。此外,它可能在某些并发场景下发生活锁。我将把解决此类问题作为练习。:-)
在您编辑的问题中,您提出:
我有 10 个进程尝试使用 open(O_CREAT) 调用或多或少地同时打开同一个文件,然后将其删除。
一种黑客式但更防弹的解决方案是为每个进程提供不同的用户 ID。然后,只需使用常规open(path, O_CREAT|...)
呼叫即可。fstat()
然后,您可以使用文件描述符查询文件,并检查结构st_uid
的字段stat
。如果该字段等于进程的用户 ID,则它是创建者。否则,这就是一场揭幕战。这是有效的,因为每个进程都会在打开文件后删除该文件。