Почему я могу успешно перенести файл в Linux во время его написания?

Этот вопрос, я думаю, достаточно техничен для S/O и, вероятно, слишком ориентирован на программирование для Android. Я заинтригован, как файлы обрабатываются на Android (или Java или Linux, в зависимости от ситуации), поскольку я сделал что-то с моим новым смартфоном, и мне было бы интересно узнать, как это произошло.

Я переносил файл с моего ноутбука на свой Android-телефон через Bluetooth. Я увидел новый файл в проводнике файлов, предположил, что он полностью перенесен, и поэтому переместил его с /sdcard/bluetooth на /sdcard/torrents. После того, как я сделал это, я заметил, что он по-прежнему переносится. К моему удивлению, он успешно завершился, подтвержден с помощью значка уведомления в телефоне и с помощью ручной проверки MD5 с обеих сторон. В большинстве систем перемещение файла вызвало бы сбой.

В чем причина успешной передачи? Я знаю, что в общем случае путь к файлу зависит от расположения файла в файловой системе (в данном случае SD-карты). Я полагаю, что приложение Bluetooth открыло дескриптор файла, и когда я переместил файл, таблица "открытых файлов" была обновлена ​​новым путем. Является ли эта функция общепринятой для любой системы Linux? Могу ли я сделать mv в написанном файле и ожидать, что копия - в ее новом месте - будет правильной?

Ответы

Ответ 1

Когда вы перемещаете файл внутри той же файловой системы, сам файл (inode) не перемещается вообще. Единственное, что изменяется, это записи каталога в этой файловой системе. (Системный вызов, вызываемый mv в этом случае, rename(2) - проверьте эту страницу для получения дополнительной информации и ограничений.)

Когда процесс открывает файл, имя файла передается в ОС, чтобы указать, какой файл предназначен, но дескриптор файла, который вы возвращаете, вообще не связан с этим именем (вы не можете вернуть имя файла из это) – он связан с inode.
Поскольку индекс inode остается неизменным при переименовании файла (внутри той же файловой системы), процессы, которые его открывают, могут с радостью продолжать чтение и запись на него; ndash; для них ничего не изменилось, их файловый дескриптор по-прежнему действителен и указывает на правильные данные.

То же самое, если вы удаляете файл. Процессы могут продолжать читать и писать, даже если файл больше недоступен через любую запись в каталоге. (Это может привести к запутывающим ситуациям, когда df сообщает, что ваш диск заполнен, но du говорит, что вы используете гораздо меньше места, которое df сообщает. Блоки, назначенные удаленным файлам, которые все еще открыты, не будут до тех пор, пока эти процессы не закрывают дескриптор файла.)

Если mv перемещает файл через файловые системы, поведение отличается от того, что inodes специфичны для каждой файловой системы. В этом случае mv фактически скопирует данные, создав новый дескриптор (и запись каталога) в целевой файловой системе. Когда копия завершена, старый файл отсоединен и удаляется, если на нем нет открытых дескрипторов файлов, как указано выше.
В вашем случае, если вы пересекли границу файловой системы, у вас будет частичный файл в пункте назначения. И ваш процесс загрузки с радостью записывается в удаленный файл, к которому вы не можете легко получить доступ, возможно, заполнив эту файловую систему, до тех пор, пока загрузка не завершится, в этот момент индекс будет удален.

Некоторые сообщения на Unix и Linux, которые вы можете найти интересные: