如何在没有竞争条件的情况下重命名

如何在没有竞争条件的情况下重命名

本文介绍了如何在没有竞争条件的情况下重命名()?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我想将 A 重命名为 B ,但仅当 B 不存在时,天真的事情是检查 B 存在(带有 access("B",F_OK)或类似的东西),并且如果没有继续进行 rename .不幸的是,这打开了一个窗口,在此期间其他一些过程可能会决定创建 B ,然后它会被覆盖-甚至更糟的是,没有迹象表明发生过类似的事情.

If I want to rename A to B, but only if B doesn't exist, the naive thing would be checking if B exists (with access("B", F_OK) or something like that), and if it doesn't proceeding with rename. Unfortunately this opens a window during which some other process might decide to create B, and then it gets overwritten - and even worse there's no indication that something like that ever happened.

其他文件系统访问功能不受此影响- open 具有 O_EXCL (这样可以安全地复制文件),最近Linux拥有了完整的系列> * at 可以防止大多数其他竞争条件的系统调用-但不是特定条件(存在 renameat ,但可以防止完全不同的问题).

Other file system access functions don't suffer from this - open has O_EXCL (so copying files is safe), and recently Linux got an entire family of *at syscalls that protect against most other race conditions - but not this particular one (renameat exists, but protects against an entirely different problem).

那么有解决方案吗?

推荐答案

从Linux内核3.15(于2014年6月发布)开始,可以使用syscall(__ NR_renameat2,AT_FDCWD,"source-file",AT_FDCWD,"dest-file",RENAME_NOREPLACE)(包括< syscall.h> < fcntl.h> < linux/fs.h> >).

As of Linux kernel 3.15 (released in June 2014), this can be done with syscall(__NR_renameat2, AT_FDCWD, "source-file", AT_FDCWD, "dest-file", RENAME_NOREPLACE) (include <syscall.h>, <fcntl.h> and <linux/fs.h>).

这比link()更好,因为永远不会存在两个文件名同时存在的情况(特别是对于link()而言,定时断电可能会导致两个名字永远保留).

This is better than link(), because there is never a point where both filenames exist simultaneously (in particular, with link(), a precisely-timed power outage could cause both names to remain forever).

glibc 2.28(于2018年8月发布)添加了一个renameat2()包装器,因此您可以使用它而不是syscall.h和linux/fs.h(尽管您很可能需要< stdio.h> #define __GNU_SOURCE ).

glibc 2.28 (released in August 2018) adds a renameat2() wrapper, so you can use that instead of syscall.h and linux/fs.h (though you'll most likely need <stdio.h> and #define __GNU_SOURCE instead).

有关更多详细信息,请参见 http://man7.org/linux/man-pages/man2/rename.2.html(虽然在撰写本文时确实如此,但不知道 glibc 现在有一个 renameat2 包装器).

For more details, see http://man7.org/linux/man-pages/man2/rename.2.html (though it does, as of writing, not know that glibc now has a renameat2 wrapper).

这篇关于如何在没有竞争条件的情况下重命名()?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-24 20:54