为什么我可以在写入 Linux 时成功移动文件?

2022-09-01 14:02:01

我认为这个问题对于Stack Overflow来说已经足够技术性了,对于Android来说可能太注重编程了。我对Android(或Java或Linux,视情况而定)如何处理文件很感兴趣,因为我用我的新智能手机做了一些事情,我很想知道它是如何发生的。

我正在通过蓝牙将文件从笔记本电脑传输到Android手机。我在文件资源管理器中看到了新文件,以为它已完全传输,因此将其从 移动到 .在我这样做之后,我注意到它实际上仍在转移。令我惊讶的是,它成功完成,通过手机上的通知图标确认,并通过两侧的手动MD5检查进行确认。在大多数系统中,文件移动会导致崩溃。/sdcard/bluetooth/sdcard/torrents

这次成功转移的原因是什么?我知道,一般来说,文件路径与文件系统上的文件位置(在本例中为SD卡)是分开的。我想象蓝牙应用程序已经打开了文件的句柄,当我移动文件时,“打开的文件”表已使用新路径进行了更新。这个功能通常适用于任何Linux系统吗?我可以对正在写入的文件执行一个操作,并期望副本 ( 在其新位置 - 是正确的吗?mv


答案 1

当您在同一文件系统中移动文件时,文件本身(inode)根本不会移动。唯一更改的是该文件系统中的目录条目。(在这种情况下调用的系统调用是 rename(2) - 检查该页面以获取更多信息和限制。mv

当进程打开文件时,文件名将传递到操作系统以指示要表示的文件,但是您返回的文件描述符根本不链接到该名称(您无法从中获取文件名) - 它链接到inode。
由于当您重命名文件时 inode 保持不变(在同一文件系统中),因此打开它的进程可以愉快地继续读取和写入它 - 它们没有任何变化,它们的文件描述符仍然有效并指向正确的数据。

如果您删除文件,情况也是如此。进程可以继续从中读取和写入文件,即使无法再通过任何目录条目访问该文件也是如此。(这可能会导致令人困惑的情况,即报告磁盘已满,但表示您使用的空间比报告少得多。分配给仍处于打开状态的已删除文件的块不会释放,直到这些进程关闭其文件描述符。dfdudf

如果跨文件系统移动文件,则行为是不同的,因为 inode 特定于每个文件系统。在这种情况下,将实际复制数据,在目标文件系统上创建新的 inode(和目录条目)。复制结束后,将取消链接旧文件,如果其上没有打开的文件句柄,则将其删除,如上所述。
在你的例子中,如果你越过了文件系统边界,那么你的目标中就会有一个部分文件。您的上传过程愉快地写入您无法轻松访问的已删除文件,可能会填满该文件系统,直到上传完成,此时inode将被丢弃。mvmv

一些关于Unix和Linux的帖子,你可以发现很有趣:


答案 2

推荐