Почему текущий каталог в команде ls определяется как связанный с самим собой?

В книге "Изучение операционной системы UNIX" есть раздел: "3.1.8. Список файлов", в котором описывается ls команда.

В абзаце ls -l он описывает столбцы вывода этой команды.

Второй столбец ls -l Команда содержит одно число. Этот номер указан в книге как "Количество файлов и каталогов, связанных с этим". (связан с файлом или каталогом, названным в последнем столбце той же строки, что и соответствующий номер.)

Я попробовал эту команду и сравнил вывод с фактическим количеством файлов и каталогов в текущем каталоге.

ls -l
drwxr-xr-x   6 azbc  staff    192 Sep  7 16:09 test

В каталоге testУ меня есть 2 подкаталога и 1 файл, 1 скрытый файл и список текущего каталога, плюс список родительского каталога, таким образом, вместе 6 файлов и каталогов.

 ls -a -F
 ./                .hidden_file.txt  dir_2/
 ../               dir_1/            file_1.sh

Мне кажется логичным идентифицировать все файлы и каталоги (включая скрытые файлы и каталоги) как связанные с текущим каталогом. Также кажется логичным идентифицировать родительский каталог как связанный с текущим каталогом.

Но почему текущий каталог идентифицирован как связанный с самим собой?

ls -la Команда для тестовой директории дает следующий вывод. (опция -F показывает / в случае каталога за именем каталога и * в случае исполняемого файла)

 ls -la -F
 total 0
 drwxr-xr-x   6 azbc  staff   192 Sep  7 16:09 ./
 drwxr-xr-x+ ?? azbc  staff    ?? Sep  7 16:06 ../
 -rw-r--r--   1 azbc  staff     0 Sep  7 16:09 .hidden_file.txt
 drwxr-xr-x   2 azbc  staff    64 Sep  7 16:06 dir_1/
 drwxr-xr-x   2 azbc  staff    64 Sep  7 16:06 dir_2/
 -rwx--x--x   1 azbc  staff     0 Sep  7 16:06 file_1.sh*

Сам файл идентифицируется только одной ссылкой. Файл связан с самим собой? Или это связано с каталогом, в котором он находится?

Поскольку в листинге каталога сам каталог представлен в листинге и, следовательно, логично считаться ссылкой.

Однако в листинге самого файла есть только сам файл, представленный в листинге.

 ls -la -F file_1.sh
 -rwx--x--x  1 azbc  staff  0 Sep  7 16:06 file_1.sh

Это логично сказать, что файл связан с самим собой.

Однако мне кажется более логичным сказать, что файл связан с каталогом, в котором он находится.

Это кажется не последующим.

Или листинг связанных файлов - это просто подсчет файлов и каталогов, присутствующих в выводе листинга команды, а не идентификация реальных ссылок на файл или каталог в файловой системе?

Редактировать: как ответ @George Udosen, на:

"Теперь, чтобы попытаться ответить на ваш запрос в комментарии:

"Что здесь указано в качестве ссылки? Сам файл указан в списке? Или каталог, в котором находится указанный файл? "

Если я перечислю каталог test:

 ls -la -F test
 ...
 drwxr-xr-x   2 azbc  staff    64 Sep  7 16:06 dir_1/
 ...
 -rwx--x--x   1 azbc  staff     0 Sep  7 16:06 file_1.sh*

это идентифицирует каталог dir_1 с 2 ссылки!

Если я тогда перечислю этот каталог test/dir_1

 ls -la -F test/dir_1
 total 0
 drwxr-xr-x  2 azbc  staff   64 Sep  7 16:06 ./
 drwxr-xr-x  9 azbc  staff  288 Sep  7 21:37 ../

Эй, действительно! это списки 2 записи!

Файл file_1.sh* был идентифицирован с 1 ссылка на сайт. Если я перечислю файл file_1.sh

 ls -la -F test/file_1.sh
 -rwx--x--x  1 azbc  staff  0 Sep  7 16:06 test/file_1.sh*

Хо!! это действительно список 1 вход!! а именно file_1.sh сам! и снова идентифицирует этот файл с 1 запись.

Кстати, из этого я могу сделать вывод, что каждая из перечисленных 1 ссылка это файл а не каталог? Но это не так, поскольку символические ссылки также перечислены как имеющие 1 ссылка на сайт / 1 запись.

3 ответа

Решение

Я рекомендую вам прочитать Что такое каталоги, если все в Linux является файлом? для более глубокого знания структуры каталогов, истории и терминологии того, как работают каталоги и их элементов (inode, dirent структура и т. д.), хотя это не требуется для этого вопроса.

Что такое точка '.' и точка-точка '..' каталоги?

Смотря на format of directories Страница справочника издателя руководства UNIX 1971 года, мы видим, что . а также .. были уже там

По соглашению, первые две записи в каждом каталоге предназначены для "." а также "..". Первый - это запись для самого каталога.

Что касается их значения, ответ можно найти на ответе Паноса. Кен Томпсон объяснил, как .. произошло в интервью 1989 года:

Каждый раз, когда мы делали каталог, мы условно помещали его в другой каталог, называемый каталог - каталог, который был dd. Его имя было dd и что все пользовательские каталоги и фактически большинство других каталогов, пользователи поддерживают свои собственные системы каталогов, имеют указатели на dd, а dd сокращен до "dot-dot", а dd предназначен для directory-directory. Это было то место, куда вы могли попасть во все другие каталоги системы, чтобы поддерживать миску спагетти.

Естественно, . как вы можете догадаться расшифровывается как d или не хватает directory, Такой каталог сам по себе имеет тот же номер инода, что и фактическое имя каталога. Теперь это еще не объясняет, почему каталог . связано с собой, но у меня есть пара идей.

0. Unix Философия:

В книге 1996 года "Внутренние органы UNIX: новые границы" Уреша Вахалии в главе 8 на странице 222 говорится:

Unix поддерживает назначение текущего рабочего каталога для каждого процесса, который поддерживается как часть состояния процесса. Это позволяет пользователям ссылаться на файлы по их относительным путям, которые интерпретируются относительно текущего каталога.

Учитывая, что каталог - это просто специальный файл, нам нужно постоянное относительное имя файла для ссылки на сам каталог, и это будет специальное имя файла ., который эволюционировал из d, который был сокращен для каталога.

1. Технические преимущества

Основное преимущество, которое я могу придумать, заключается в том, что система упрощает поиск инода и, следовательно, информацию метаданных. Поскольку в каталоге уже есть запись, содержащая . с тем же индексом нет необходимости запрашивать полный путь. То же самое касается программирования. Рассмотрим очень простую реализацию ls, Там я использую getcwd() функция, чтобы получить текущий рабочий путь каталога, а затем передать его opendir(), Или я мог бы выбросить getcwd() и просто использовать opendir('.') непосредственно. Во времена старых терминалов PDP-11, где объем памяти составлял несколько килобайт, экономия на служебных вызовах системного вызова имела решающее значение.

2. Удобство для пользователя:

Рассмотрим следующий пример:

mv ../filename.txt .

В презентации Хендрика Яна Томассена было упомянуто, что оригинальные команды Unix были короткими из-за того, что старые клавиши терминала были трудны для нажатия, поэтому было физическим усилием фактически вводить команды весь день. Если вы углубились в дерево каталогов, перепечатка полного пути текущего рабочего каталога будет утомительной. Конечно, mv может быть реализовано с предположением, что, когда мы делаем mv <file> мы подразумеваем пункт назначения как "текущий рабочий каталог". Я могу только догадываться, почему mv <original> <new> преобладал, возможно, из-за влияния других языков программирования того времени.

3. Улучшение над МУЛЬТИКОЙ:

Примечание: я никогда не работал над MULTICS, поэтому он основан только на чтении онлайн-источников.

В соответствии с руководством MULTICS 1986 года по именам путей:

Относительный путь может начинаться с одного или нескольких символов меньше ("<").

> символ используется в MULTICS в качестве разделителя пути (например, / в Linux). Возможно, это может выглядеть запутанным. Таким образом, ./ когда ссылка на команду, возможно, яснее - мы ссылаемся на имя файла, которое находится в текущем рабочем каталоге.

Это может быть полезно для других команд. Хорошо известно, как создать файл в Unix / Linux: touch ./file, На MULTICS, согласно swenson.org, это делается через an или же add_name команда:

cd foo
r 18:03 0.041 1

an foo bar
r 18:03 0.077 3

ls foo

Directories = 1.

sma  foo
       bar

r 18:03 0.065 0

С другой стороны, есть очевидное сходство, когда дело доходит до ..: перемещение по одному каталогу осуществляется через cwd <<,

4. Ссылка на исполняемые файлы

Если вы запускаете сценарии ежедневно, вы хорошо знаете ./script.sh синтаксис. Причина этого проста: оболочка работает так, что ищет исполняемые файлы в PATH переменная, поэтому, когда вы предоставляете ./ это не должно смотреть нигде. Магия PATH переменная - это то, что заставляет вас использовать echo вместо /bin/echo или другие очень длинные пути. Теперь скажем, у вас этого нет script.sh на вашем пути, и он там в вашем текущем рабочем каталоге. Чем вы сейчас занимаетесь? Тип /very/long/path/to/the/executable/this/typing/gets/exhausting/on/PDP-11/finally/script.sh? Это отбросит всю концепцию простоты Unix! Итак, возвращаясь к философии Unix, она также согласуется с принципом элегантного дизайна / простоты.

Конечно, некоторые люди хотят добавить . в PATH, но на самом деле это очень плохая практика, так что не делайте этого.

примечание: особый случай .. а также . указывая на то же самое, это индекс 2 - / dir, и это имеет смысл, поскольку это самая высокая точка в дереве каталогов. Конечно, .. NULL также может работать, но более элегантно / сам.


Примечание о количестве ссылок и жестких ссылках каталогов

Как правильно указал Жиль (на что ссылается Джордж Удосен), счетчик ссылок для каталога начинается с 2 (.. для родительского каталога и .), со всей дополнительной ссылкой, являющейся подкаталогом:

# new directory has link count of 2
$ stat --format=%h .
2
# Adding subdirectories increases link count
$ mkdir subdir1
$ stat --format=%h .
3
$ mkdir subdir2
$ stat --format=%h .
4
# Adding files doesn't make difference
$ cp /etc/passwd passwd.copy
$ stat --format=%h .
4
# Count of links for root
$ stat --format=%h /
25
# Count of subdirectories, minus .
$ find / -maxdepth 1 -type d | wc -l
24

Интуитивно понятно, что ссылки на каталоги являются только подкаталогами - имеет смысл, поскольку жесткие ссылки имеют то же время, что и исходный файл. За исключением того, что это не совсем жесткие ссылки - жесткие ссылки создают имя файла, которое указывает на те же данные. По этому определению жесткая ссылка на каталог будет содержать те же данные, т.е. содержать одинаковый список файлов. Это может привести к зацикливанию в файловой системе или множеству потерянных файлов, если будут удалены все жесткие ссылки на каталог. По этой причине создание жестких ссылок для каталогов недопустимо, и если использовать фразу Жиля из другого вопроса (который я рекомендую вам прочитать) "...[на самом деле, многие файловые системы имеют жесткие ссылки на каталоги, но только в очень дисциплинированный способ..."и это особые случаи . а также .. каталоги.

Теперь возникает вопрос: что на самом деле означает "ссылки" в контексте каталогов? TL;DR: структура каталогов является деревом, и здесь Ссылки означают количество дочерних узлов для каждого элемента дерева (с каждым листом или каталогом без подкаталогов, имеющим только 2 ссылки). В частности, ext3 и ext4 используют HTree, а xfs использует дерево B+


Заключение

В конце концов, причина, почему . связано с собой просто потому, что это хороший дизайн. Первоначальные авторы Unix, возможно, работали с технологическими ограничениями своего времени, но они были одними из самых блестящих умов того времени или, как часто их называют, "волшебниками", и они делали что-то по какой-то причине.

Взято из этого превосходного ответа Жиля

Исторически первая файловая система Unix создавала две записи в каждом каталоге: . указывая на сам каталог, и .. указывая на своего родителя. Это обеспечило простой способ обхода файловой системы, как для приложений, так и для самой ОС.

Таким образом, каждый каталог имеет количество ссылок 2+n, где n - это количество подкаталогов. Ссылки являются записью для этого каталога в его родительском, собственном каталоге . запись и .. запись в каждом подкаталоге. Например, предположим, что это содержимое поддерева с корнем в /parent, все каталоги:

/parent
/parent/dir
/parent/dir/sub1
/parent/dir/sub2
/parent/dir/sub3

затем dir имеет количество ссылок 5: dir вход в /parent, . вход в /parent/dirи три .. записи в каждом из /parent/dir/sub1, /parent/dir/sub2 а также /parent/dir/sub3, поскольку /parent/dir/sub1 не имеет подкаталога, его количество ссылок равно 2 (sub1 вход в /parent/dir и . вход в /parent/dir/sub1).

Чтобы минимизировать количество специального кожуха для корневого каталога, у которого нет "правильного" родителя, корневой каталог содержит .. запись, указывающая на себя. Таким образом, он также имеет счетчик ссылок 2 плюс количество подкаталогов, причем 2 /. а также /..,

Более поздние файловые системы имели тенденцию отслеживать родительские каталоги в памяти и обычно не нуждаются . а также .. существовать как фактические записи; типичные современные системы Unix лечения . а также .. как специальные значения как часть кода файловой системы, независимого от типа файловой системы. Некоторые файловые системы все еще включают . а также .. записи или делать вид, даже если на диске ничего не появляется.

Большинство файловых систем по-прежнему сообщают о количестве ссылок 2+n для каталогов независимо от того, . а также .. Записи существуют, но есть исключения, например, btrfs не делает этого.

Теперь попробуем ответить на ваш запрос в комментарии:

Что здесь указывается в виде ссылки? Сам файл указан в списке? Или каталог, который содержит файл в списке?

Эта ссылка принадлежит файлу, а не каталогу. Позвольте мне привести пример, чтобы проиллюстрировать этот факт. Теперь, если бы я должен был сделать nano file.txt, ссылка здесь будет использоваться для поиска inode номер для этого файла и inode впоследствии предоставит информацию, которая позволит nano Программа изменяет этот файл. Помните, что inode содержит информацию об этом файле (будь то папка, файл или блочное устройство).

Теперь каждое имя файла должно быть связано с inode number для обычных операций над этим файлом, так что да, эта ссылка принадлежит этому файлу, а не родительскому. Надеюсь, я правильно понял ваш вопрос и тоже ответил на него.

Ваш вопрос для меня неясен, но я пытаюсь объяснить, как все работает, чтобы это могло помочь вам понять это.

Каждый файл, хранящийся в системе, имеет номер (номер индекса), давайте проверим это:

$ ls -i -1 -a test/
9186865 .
9175041 ..

я использовал -1 показать список файлов в одном столбце и -iдля показа инодов и -a показать скрытые файлы.

каждый inode хранит информацию о файлах, такие как права доступа, владелец, размер, количество ссылок, время модификации, указатели на данные фактических файлов (но не имя файла).

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

Поэтому, когда я удаляю файл (также известный как удаление связи с файлом), я удаляю его ссылку из родительского каталога, но данные все еще живут на диске.

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

И, как вы знаете, . это жесткая ссылка на текущий каталог и .. это жесткая ссылка на родительский каталог, поэтому, если я создаю новый каталог:

$ mkdir test
$ ls -i -d test
9186865 drwxrwxr-x 2 ravexina ravexina 4096 Sep  7 19:37 test

Как вы можете видеть, количество ссылок равно двум, теперь не имеет значения, сколько файлов я создаю в этом каталоге, количество ссылок останется неизменным, если я не начну создавать каталоги. для каждого каталога число будет увеличиваться на 1, и теперь вы знаете, почему! потому что каждый новый каталог содержит жесткую ссылку на своего родителя: ..:

Помните, что я сказал о каталогах?

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

Ссылки на самом деле являются этими именами, каждый файл по умолчанию имеет 1 ссылку (его имя при создании) теперь, если вы создаете новую жесткую ссылку на этот файл (означает другое имя, в другом каталоге или в том же каталоге, который указывает на те же данные [inode]) число будет увеличено на 1.

Другие вопросы по тегам