为什么我可以在写入Linux时成功移动一个文件? [英] Why can I successfully move a file in Linux while it is being written to?

查看:195
本文介绍了为什么我可以在写入Linux时成功移动一个文件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我认为这个问题对于S / O来说是足够的技术,可能也是针对 Android 的面向编程的。我对如何在Android(或Java或Linux,如适用)中处理文件很感兴趣,因为我用我的新智能手机做了一些事情,我很想知道它是怎么发生的。

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



成功传输的原因是什么?我知道,一般来说,文件路径与文件系统上的文件位置(在这种情况下是SD卡)是分开的。我想蓝牙应用程序已打开文件的句柄,当我做文件移动时,一个打开的文件表更新了一个新的路径。这个功能在任何Linux系统中都是如此吗?我可以在正在写入的文件上做一个 mv ,并期望在新位置的副本是正确的吗?

内移动文件时,文件本身( inode )根本不会移动。 唯一改变的是该文件系统中的目录条目。 (在这种情况下,由 mv 调用的系统调用是 rename(2) - 检查该页面是否有其他信息和限制。)



当一个进程打开一个文件时,文件名被传递给操作系统来表示哪个文件是这个文件的意思,但是你得到的文件描述符根本没有链接到这个名字无法取回它的文件名)–它链接到inode。

由于inode在重命名文件(在同一个文件系统内)时保持不变,所以打开的进程可以愉快地继续读取和写入文件。他们的文件描述符仍然是有效的,并指向正确的数据。

如果你删除一个文件,也是如此。即使文件不能通过任何目录条目进入,进程也可以继续读写。 (这可能会导致令人困惑的情况,其中 df 报告您的磁盘已满,但 du 表示您正在使用 df 报告的空间更少,分配给已删除文件的块将不会被释放,直到这些进程关闭它们的文件描述符为止。)

如果 mv 跨文件系统移动文件,则行为是不同的,因为inode是特定于每个文件系统的。在这种情况下, mv 将实际上复制数据,在目标文件系统上创建一个新的inode(和目录项)。当复制结束时,旧文件被取消链接,如果没有打开的文件句柄,则删除,如上所示。

在你的情况下,如果你已经跨越了一个文件系统边界,你会有一个在目的地的部分文件。上传过程愉快地写入一个你不能轻易访问的被删除的文件,可能会填满那个文件系统,直到上传完成之后inode会被丢弃。



Unix& Linux ,你可以找到有趣的:


This question I think is technical enough for S/O, and probably too programming-oriented for Android. I'm intrigued as to how files are handled in Android (or Java or Linux, as appropriate), since I did something with my new smartphone and I'd curious to know how it happened.

I was transferring a file from my laptop to my Android phone, via Bluetooth. I saw the new file in the file explorer, assumed it was fully transferred, and so moved it from /sdcard/bluetooth to /sdcard/torrents. After I had done so, I noticed it was in fact still being transferred. To my surprise, it completed successfully, confirmed with a notification icon in the phone, and by a manual MD5 check on both sides. In most systems, the file move would have caused a crash.

What is the reason for this successful transfer? I'm aware that in general, the file path is separate to the file location on the file system (in this case, an SD card). I imagine that the Bluetooth app has opened a handle to the file, and when I did the file move, a table of 'open files' was updated with a new path. Is this feature generally true of any Linux system? Could I do a mv on a file being written and expect the copy - in its new location - to be correct?

解决方案

When you move a file inside the same filesystem, the file itself (the inode) isn't moved at all. The only thing that changes are the directory entries in that filesystem. (The system call invoked by mv in this case is rename(2) - check that page for additional information and restrictions.)

When a process opens a file, the filename is passed to the OS to indicate which file is meant, but the file descriptor you get back isn't linked to that name at all (you can't get back a filename from it) – it is linked to the inode.
Since the inode remains unchanged when you rename a file (inside the same filesystem), processes that have it open can happily keep reading from and writing to it – nothing changed for them, their file descriptor is still valid and pointing to the right data.

Same thing if you delete a file. Processes can keep reading and writing from it even if the file is no longer reachable through any directory entry. (This can lead to confusing situations where df reports that your disk is full, but du says you're using much less space that df reports. The blocks assigned to deleted files that are still open won't be released until those processes close their file descriptor.)

If the mv moves the file across filesystems, then the behavior is different since inodes are specific to each filesystem. In that case, mv will actually copy the data over, creating a new inode (and directory entry) on the destination filesystem. When the copy is over, the old file is unlinked, and removed if there are no open filehandles on it, as above.
In your case, if you had crossed a filesystem boundary, you'd have a partial file in the destination. And your upload process happily writing to a deleted file you can't easily access, possibly filling up that filesystem, until the upload finished at which point the inode would get dropped.

Some posts on Unix & Linux that you could find interesting:

这篇关于为什么我可以在写入Linux时成功移动一个文件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆