Какова концепция создания файла с нулевыми байтами в Linux?

32

Если я сделаю следующее:

touch /tmp/test

а затем выполнить

ls -la /tmp/

Я мог видеть testфайл с 0 байтами в каталоге.

Но как операционная система обрабатывает концепцию 0 байтов . Если я изложу это в терминах непрофессионала:

0 Байт вообще не является памятью, следовательно, ничего не создано.

Создание файла, должно или должно по крайней мере требовать определенной памяти, верно?

Shan-Десаи
источник

Ответы:

63

Файл - это (примерно) три отдельные вещи:

  • «Inode», структура метаданных, которая отслеживает, кто владеет файлом, разрешениями и списком блоков на диске, которые на самом деле содержат данные.
  • Одна или несколько записей каталога (имен файлов), которые указывают на этот индекс
  • Фактические блоки самих данных

Когда вы создаете пустой файл, вы создаете только индекс и запись каталога, указывающую на этот индекс. То же самое для разреженных файлов ( dd if=/dev/null of=sparse_file bs=10M seek=1).

Когда вы создаете жесткие ссылки на существующий файл, вы просто создаете дополнительные записи каталога, которые указывают на тот же индекс.

Я упростила вещи здесь, но вы поняли идею.

xhienne
источник
2
красиво сказано. продвигая одну небольшую головоломку с помощью вашего абзаца «жестких ссылок»: если создается жесткая ссылка на пустой файл, который, как вы заявляете, не имеет списка блоков, как эта жесткая ссылка может указывать на (тот же) список блоков которые не существуют?
Феофраст
4
@ Теофраст Хороший вопрос. Я сделал возможным упростить вещи. На самом деле между списком блоков и записями каталога существуют метаданные, относящиеся к файлу (на которые указывает номер индекса), и которые содержат атрибуты файла (владелец, разрешения, ...) и расширенные атрибуты. Список блоков там. Таким образом, все записи каталога указывают не на список блоков (FAT), а на метаданные.
xhienne
6
Должны быть три отдельные вещи: список блоков, которые содержат данные; сами блоки ; и запись каталога (или записи), которая указывает на список блоков.
Подстановочный
@Wildcard Я отправил правку, сделав три вещи, и сослался на индекс по имени. И индекс, и каталог являются метаданными; но это разные виды метаданных. Файл всегда имеет один индекс и по крайней мере одну запись в каталоге. Этот индекс может содержать пустой список блоков данных.
Монти Хардер
1
@Wildcard Даже если вы новичок, важно понимать разницу между индексом и каталогом. Когда кто-то меняет права доступа / владельца «имени каталога» и думает, что другие ссылки на тот же индекс сохранят старые права доступа / владельца, может произойти что-то очень плохое. Нам не нужно углубляться в детали того, как inode ссылается на прямые блоки, косвенные блоки, дважды и трижды косвенные блоки, чтобы понять, что это список блоков. Или что список может быть пустым.
Монти Хардер
24

touchсоздаст инод и ls -iили statпокажет информацию об иноде:

$ touch test
$ ls -i test
28971114 test
$ stat test
  File: ‘test’
  Size: 0           Blocks: 0          IO Block: 4096   regular empty file
Device: fc01h/64513d    Inode: 28971114    Links: 1
Access: (0664/-rw-rw-r--)  Uid: ( 1000/1000)   Gid: ( 1000/1000)
Access: 2017-03-28 17:38:07.221131925 +0200
Modify: 2017-03-28 17:38:07.221131925 +0200
Change: 2017-03-28 17:38:07.221131925 +0200
 Birth: -

Обратите внимание, что testиспользуется 0 блоков. Для хранения отображаемых данных индекс использует несколько байтов. Эти байты хранятся в таблице inode. Посмотрите на странице ext2 пример структуры inode .

CTX
источник
19

ls(или, ну, stat(2)системный вызов) сообщает вам размер содержимого файла. То, сколько места нужно файловой системе для бухгалтерии, не является частью этого, и как деталь реализации, это не то, о чем программы вообще должны заботиться или даже знать. Если сделать детали реализации видимыми, абстракция файловой системы станет менее полезной.

ilkkachu
источник
9

Сам файл не занимает никакого места, но файловая система занимает, сохраняя имя файла, местоположение, права доступа к нему и тому подобное.

Патрик Бухер
источник
4
Если вы посмотрите на пространство, занимаемое записью каталога, если у вас есть каталог, содержащий тысячу файлов размером 0 байт, каталог будет больше, чем запись каталога, содержащая всего 2 огромных файла.
Марк Стюарт,
2
необходимо упомянуть, что файл - это абстрактное понятие, которое не тесно связано с его физическим представлением, например, на диске.
Флориан Кастеллан
5

Простой ответ: потому что так определено.

Более длинный ответ: это определено таким образом, потому что некоторые операции концептуально проще:

  • Если файл содержит 20 букв «А» и вы удалили все буквы «А», то этот файл станет на 20 байт короче. Та же самая операция с файлом, который состоял только из «AAAAAAAAAAAAAAAAAAAA», должна была бы иметь дело со специальным случаем исчезающего файла.
  • На практике, удаление последней строки текстового файла должно осуществляться в специальном случае.
  • Текстовым редакторам, которые регулярно создают резервную копию, потребуется специальный код, чтобы справиться с ситуацией, когда пользователь может удалить последнюю строку, перейти к ланчу, а затем вернуться и добавить еще одну строку. Дополнительные осложнения возникают, если некоторые другие пользователи в то же время создали файл с таким именем.

Вы можете сделать больше вещей: * Файлы журнала ошибок, как правило, создаются пустыми, заполняются тогда и только тогда, когда происходит ошибка. * Чтобы узнать, сколько ошибок произошло, вы подсчитываете количество строк в лог-файлах. Если файл журнала пуст, количество ошибок равно нулю, что имеет смысл. * Иногда вы видите файлы, где весь соответствующий текст находится в имени файла, например this-is-the-logging-directory. Это препятствует тому, чтобы чрезмерные администраторы удаляли пустые каталоги после установки, и также предотвращает ошибки, когда программа или пользователь случайно создают файл, где программа хотела бы видеть каталог позже. gitПрограмма (и другие) , как правило, игнорируют пустые каталоги, и если проект / администратор / пользователь хочет иметь запись о том , что каталог существует , даже если он не имеет никакого полезного содержания (пока), вы можете увидеть пустой файл с именемemptyили empty.directory.

Никакие операции не становятся более сложными:

  • Конкатенация файлов: это просто неоперация с пустым файлом.
  • Поиск строки в файле: это охватывается стандартным случаем «если файл короче поискового термина, он не может содержать поисковый термин».
  • Чтение из файла: программы должны иметь дело с попаданием в конец файла, прежде чем они получат то, что ожидали, поэтому снова случай файла нулевой длины не требует дополнительного мышления для программиста: он просто нажмет конец -файл с самого начала.

В случае файлов аспект «где-то записан файл» (inode и / или имя файла) стоит поверх вышеупомянутых соображений, но файловые системы не сделали бы этого, если бы пустые файлы были бесполезны.

Как правило, все вышеперечисленные причины, кроме связанных с именами файлов, относятся к последовательностям. Прежде всего это касается строк, представляющих собой последовательности символов: строки нулевой длины являются обычным явлением внутри программ. Строки обычно запрещены на уровне пользователя, если они не имеют смысла: имя файла является строкой, и большинство файловых систем не допускает пустую строку в качестве имени файла; внутренне, при создании имен файлов из фрагментов, программа может иметь пустую строку в качестве одного из фрагментов.

toolforger
источник
1

Используя простейшую аналогию:

Давайте сравним файл, скажем, со стаканом воды.

«touch / tmp / test» очень похож на создание пустого стакана без воды. Стекло пустое, поэтому его размер равен нулю. Но стекло существует.

На языке файловой системы стекло - это метаданные, а содержимое стекла - это данные. Мета-данные содержат все виды вещей, как упоминалось в предыдущих постах.

Файлы нулевого размера могут быть полезны. Одним из примеров является использование их в качестве хлебной крошки, где его простое существование может использоваться для указания какого-либо состояния (т. Е. Если файл существует: тогда что-то сделать; если нет: игнорировать).

Эль Стеферино
источник
0

Подумайте об этом так: скажите, что программа отслеживает запросы SQL, отправленные на ваш сервер. Программа хочет указать, что она регистрирует запросы в простой текстовый файл, но еще не было зарегистрировано ни одного запроса. Как это должно выглядеть? Я бы сказал, что это должен быть файл нулевого размера в /var/log/acme-sql-server/queries.log. Таким образом, вы можете выяснить, когда началась запись в журнал (время создания файла), когда он последний раз обновлялся (т.е. когда он был создан), сколько запросов было записано (количество новых строк в файле = 0) и кто ведет запись в журнал. (Acme SQL Server). В таких случаях полезно иметь концепцию пустого файла, который, тем не менее, существует в определенном месте.

Gaurav
источник