在检查文件是否存在然后创建它时如何避免竞争条件?

问题描述:

我正在考虑代码中的极端情况,当您检查文件是否存在时,我无法弄清楚如何避免问题,如果不存在,则使用该文件名创建一个文件.代码大致如下:

I'm thinking of corner cases in my code and I can't figure out how to avoid problem when you check if file exists, and if it does not, you create a file with that filename. The code approximately looks like this:

// 1
status = stat(filename);
if (!status) {
  // 2
  create_file(filename);
}

在调用 1 和 2 之间,另一个进程可以创建文件名.如何避免这个问题,是否有针对此类问题的通用解决方案?它们经常发生在系统编程中.

Between the call to 1 and 2 another process could create the filename. How to avoid this problem and is there a general solution to this type of problems? They happen often in systems programming.

这就是O_EXCL |open() 的 O_CREAT 标志用于:

This is what the O_EXCL | O_CREAT flags to open() were designed for:

如果设置了 O_CREAT 和 O_EXCL,如果文件存在,open() 将失败.检查文件是否存在以及如果文件不存在则创建文件对于执行 open() 的其他线程来说是原子的,该线程在设置了 O_EXCL 和 O_CREAT 的同一目录中命名相同的文件名.如果设置了 O_EXCL 和 O_CREAT,并且路径命名为符号链接,则 open() 将失败并将 errno 设置为 [EEXIST],无论符号链接的内容如何.如果设置了 O_EXCL 而未设置 O_CREAT,则结果未定义.

If O_CREAT and O_EXCL are set, open() shall fail if the file exists. The check for the existence of the file and the creation of the file if it does not exist shall be atomic with respect to other threads executing open() naming the same filename in the same directory with O_EXCL and O_CREAT set. If O_EXCL and O_CREAT are set, and path names a symbolic link, open() shall fail and set errno to [EEXIST], regardless of the contents of the symbolic link. If O_EXCL is set and O_CREAT is not set, the result is undefined.

所以:

fd = open(FILENAME, O_EXCL | O_CREAT | O_RDWR);
if (fd <0) { /* file exists or there were problems like permissions */
    fprintf(stderr, "open() failed: \"%s\"\n", strerror(errno));
    abort();
}
 /* file was newly created */