我们有基于 beaglebone black 的定制板,具有 256MB RAM 和 4GB eMMC。主板运行 Linux 内核 4.9
我们遇到了一种情况,我们在其中创建一个文件,tempfs
然后在验证后,我们必须将它移动到 eMMC 的 ext4 分区。只归档一个certificate
在某些情况下,我们在一个目录中有多个证书,因此我们必须将整个目录从 tempfs 移动到 eMMC 上的 ext4 分区。
所以我们担心的问题之一是atomicity
(mv
移动)操作。
根据rename
系统调用 Linux 手册页重命名文件是一个原子操作。
http://man7.org/linux/man-pages/man2/rename.2.html
但是我们不确定重命名操作是否涉及在两个文件系统之间移动文件,原子性是否仍然可用。所以问题是将文件从原子移动tmpfs
到ext4
原子吗?
显然,一种可能的解决方案是将文件保存在同一分区上的不同文件夹中(显然在同一文件系统上)并使用mv
. 对于使用以下重命名方法的目录
SRC_dir --> TMP_DEST_dir
DEST_dir --> BAK_DEST_dir
TMP_DEST_dir --> DEST_dir
delete BAK_DEST_dir
对替代品有什么建议吗?
编辑
收到回复后,我尝试在板上执行以下测试代码,
#include <stdio.h>
#include <errno.h>
int main()
{
int retcode = 0;
system("touch /tmp/rename_test");
retcode = rename("/tmp/rename_test", "/home/fs_rename_test");
if ( retcode < 0) {
printf("errno : %d\n",errno );
perror("Error occurred while renaming file");
return 1;
}
return 0;
}
返回以下输出。并确认重命名不能跨文件系统工作。
errno : 18
Error occurred while renaming file: Invalid cross-device link
不可以。这样的重命名只能在文件系统中使用。手册页
rename(2)
明确提到了尝试跨挂载点重命名时返回的错误:跨文件系统的移动需要结合复制和删除来完成。如果不起作用,它将
mv
为您执行此操作,但在这种情况下它不会是原子的。rename()
解决这个问题的简单方法确实是首先将文件复制到同一文件系统上的临时位置。一般来说,将临时文件放在与最终目的地相同的目录中是最简单的,因为这是唯一可以保证在同一个文件系统上的地方。当然,这要求任何处理文件的进程都将有一些逻辑来忽略基于其名称的临时文件。
大致来说,这样的事情应该适用于一个文件:
请注意,您为目录描述的过程本质上是这样的:
这还不错,但不是原子的。
mv
两次运行(或调用)之间有一段时间rename()
,当时/dst/dir
不存在。这可以通过通过符号链接访问目录来解决,因为可以用重命名原子地替换链接。