我有10个进程尝试使用open(O_CREAT)调用同时或多或少地打开同一个文件,然后删除它。是否有任何可靠的方法来确定哪个进程实际创建了文件,哪个进程已经打开已创建文件,例如,如果我想准确计算在这种情况下打开该文件的次数。
我想我可以在文件打开操作上放置一个全局互斥,并使用O_CREAT和O_EXCL标志执行一系列open()调用,但这不符合我对“robust”的定义。
答案 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,那么它就是创建者。否则,这是一个开场白。这是有效的,因为每个进程在打开后都会删除该文件。