Чому жорсткі посилання на каталоги не дозволяються в UNIX / Linux?


130

Я читаю в підручниках, що Unix / Linux не дозволяє жорсткі посилання на каталоги, але дозволяють м'які посилання. Це тому, що коли ми маємо цикли і якщо створюємо жорсткі посилання, а через деякий час видаляємо оригінальний файл, це вказуватиме на якесь значення сміття?

Якщо цикли були єдиною причиною заборони жорстких посилань, то чому дозволяються м'які посилання на каталоги?


2
Де слід ..вказати? Особливо після видалення жорсткого посилання на цей каталог, у каталог, на який вказує ..? Це потрібно кудись вказати.
Thorbjørn Ravn Andersen

2
..фізично не потрібно існувати на будь-якому накопичувачі. Завдання операційної системи у будь-якому разі відслідковувати поточну робочу директорію, тому слід також відносно просто зберігати список входів, пов'язаних з кожним процесором cwd, і посилатися на це, коли він бачить використання ... Звичайно, це означатиме, що потрібно посилатися на символьні посилання, але ви вже повинні бути обережними, щоб не порушити символьні посилання, і я не думаю, що додаткове правило не призведе до їх марності.
Парфянський розстріл

Мені подобається це пояснення . Короткий і легкий для читання та / або знежирення.
Тревор Бойд Сміт

Відповіді:


143

Це просто погана ідея, оскільки немає можливості сказати різницю між жорстким посиланням та оригінальним іменем.

Дозволення жорстких посилань на каталоги може порушити спрямовану ациклічну структуру графіки файлової системи, можливо, створивши петлі каталогів та звисаючі підтрубки каталогів, що зробить fsckбудь-які інші помилки ходу дерев файлів.

По-перше, щоб зрозуміти це, поговоримо про індекси. Дані у файловій системі зберігаються в блоках на диску, і ці блоки збираються разом за допомогою inode. Ви можете думати про inode як файл THE. Однак у індексах відсутні імена файлів. Ось де входять посилання.

Посилання - це лише вказівник на inode. Каталог - це inode, який містить посилання. Кожне ім'я файлу в каталозі - це лише посилання на індед. Відкриття файлу в Unix також створює посилання, але це інший тип посилання (це не назване посилання).

Жорстке посилання - це лише додатковий запис каталогу, який вказує на цей інод. Коли ви ls -l, число після дозволів - це названий кількість посилань. Більшість звичайних файлів матиме одне посилання. Створення нового жорсткого посилання на файл призведе до того, що обидві назви файлів вказують на один і той же індекс. Примітка:

% ls -l test
ls: test: No such file or directory
% touch test
% ls -l test
-rw-r--r--  1 danny  staff  0 Oct 13 17:58 test
% ln test test2
% ls -l test*
-rw-r--r--  2 danny  staff  0 Oct 13 17:58 test
-rw-r--r--  2 danny  staff  0 Oct 13 17:58 test2
% touch test3
% ls -l test*
-rw-r--r--  2 danny  staff  0 Oct 13 17:58 test
-rw-r--r--  2 danny  staff  0 Oct 13 17:58 test2
-rw-r--r--  1 danny  staff  0 Oct 13 17:59 test3
            ^
            ^ this is the link count

Тепер ви чітко бачите, що немає такого поняття, як жорстке посилання. Жорстке посилання - це те саме, що і звичайне ім'я. У наведеному вище прикладі, testабо test2, що є оригінальним файлом і який є твердим посиланням? Зрештою, ви не можете насправді сказати (навіть за часовими позначками), оскільки обидва назви вказують на один і той же вміст, на один і той же індет

% ls -li test*  
14445750 -rw-r--r--  2 danny  staff  0 Oct 13 17:58 test
14445750 -rw-r--r--  2 danny  staff  0 Oct 13 17:58 test2
14445892 -rw-r--r--  1 danny  staff  0 Oct 13 17:59 test3

-iПрапор lsпоказує иноді номера на початку рядка. Зверніть увагу на те, як testі test2мають однаковий номер inode, але test3має інше.

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

Чому ця петля викликає занепокоєння? Тому що, коли ви проїжджаєте, немає ніякого способу виявити, що ви лупаєтеся (не відслідковуючи числа іодів під час переходу). Уявіть, що ви пишете duкоманду, яку потрібно повторити через підкаталоги, щоб дізнатися про використання диска. Як би duзнати, коли потрапив у петлю? Це схильність до помилок і багато бухгалтерського обліку, що duпотрібно було б зробити, щоб просто зняти це просте завдання.

Символьні посилання - це зовсім інший звір, оскільки вони є особливим типом "файлу", за яким багато API файлових файлових систем прагнуть автоматично слідувати. Зауважте, символьне посилання може вказувати на неіснуюче місце призначення, оскільки вони вказують по імені, а не безпосередньо на індеді. Ця концепція не має сенсу для жорстких посилань, оскільки саме існування "жорсткої посилання" означає, що файл існує.

Так чому можна duповодитися з символьними посиланнями легко і не жорсткими посиланнями? Вище ми могли переконатися, що жорсткі посилання не відрізняються від звичайних записів каталогів. Симпосилання, однак, спеціальні, виявляються та пропускаються!  duзауважує, що симпосилання - це симпосилання, і пропускає її повністю!

% ls -l 
total 4
drwxr-xr-x  3 danny  staff  102 Oct 13 18:14 test1/
lrwxr-xr-x  1 danny  staff    5 Oct 13 18:13 test2@ -> test1
% du -ah
242M    ./test1/bigfile
242M    ./test1
4.0K    ./test2
242M    .

7
Allowing hard links to directories would break the directed acyclic graph structure of the filesystem. Чи можете ви поясніть більше про проблему з циклами, використовуючи жорсткі посилання? Чому все гаразд із символьними посиланнями
user3539,

33
Вони, схоже, дозволили це зробити на Macs, додавши виявлення циклу до системного виклику link () та відмовившись дозволити створити жорстке посилання каталогу, якщо це створило б цикл. Здається, це розумне рішення.
psusi

10
@psusi mkdir -pa / b; nocheckln ca; mv ca / ​​b; - nocheckln є теоретичний ln, який не перевіряє наявність аргументів каталогів, а просто переходить на посилання, і тому що цикл не робиться, ми всі добре створюємо 'c'. тоді ми переходимо 'c' в 'a / b', і цикл створюється з / b / c -> a / - перевірка в посиланні () недостатньо хороша
Денні Дулай

3
Цикли дуже погані. У Windows є ця проблема з "переходами", які є каталогами з жорстким посиланням. Якщо ви випадково застосуєте дозволи на весь профіль, він виявить ряд стиків, які створюють нескінченний цикл. Повторне використання каталогів повторюється, поки обмеження довжини шляху не зупинять його.
doug65536

4
@WhiteWinterWolf, згідно з цим посиланням, вони спеціально додали підтримку для машини часу, але дозволено це робити лише root: superuser.com/questions/360926/…
psusi

14

За винятком точок монтування, кожен каталог має один і тільки батько: ...

Один із способів зробити pwdце - перевірити пристрій: inode на '.' і '..'. Якщо вони однакові, ви дійшли до кореня файлової системи. В іншому випадку знайдіть ім'я поточного каталогу в батьківському, натисніть його на стек і починайте порівнювати "../". з '../ ..', потім '../../.' з '../../ ..' і т. д. Після того, як ви натиснули корінь, починайте вискакувати та друкувати імена зі стека. Цей алгоритм спирається на те, що в кожному каталозі є один і тільки один з батьків.

Якщо дозволено жорсткі посилання на каталоги, на кого з кількох батьків слід ..вказати? Це одна з переконливих причин того, що жорсткі посилання на каталоги заборонені.

Посилання на каталоги не викликають цієї проблеми. Якщо програма захоче, вона може зробити lstat()на кожній частині імені шляху і виявити, коли виникає симпосилання. pwdАлгоритм повертає істинний абсолютний шлях до файлу для цільового каталогу. Те, що десь є фрагмент тексту (симпосилання), який вказує на цільовий каталог, майже не має значення. Наявність такого симпосилання не створює циклу в графі.


3
Не дуже впевнений у цьому. Якщо ми вважаємо .., що це свого роду віртуальна жорстка посилання на батьків, немає жодної технічної причини, що ціль посилання може мати лише одне інше посилання на нього. pwdдоведеться просто використовувати інший алгоритм для вирішення шляху.
Benubird

13

Ви можете використовувати прив'язку для прив'язки для імітації жорстких посилань на каталоги

sudo mount --bind /some/existing_real_contents /else/dummy_but_existing_directory
sudo umount /else/dummy_but_existing_directory

7

Мені подобається додати ще кілька пунктів щодо цього питання. Жорсткі посилання на каталоги дозволяються в Linux, але обмежено.

Один із способів ми можемо перевірити це, коли ми перераховуємо вміст каталогу, ми знаходимо два спеціальні каталоги ". і "..". Як ми знаємо "." вказує на той самий каталог і ".." вказує на батьківський каталог.

Тож давайте створимо дерево каталогів, де "a" є батьківським каталогом, який має каталог "b" як його дочірня.

 a
 `-- b

Занотуйте вкладку каталогу "a". І коли ми робимо ls -laз каталогу "a", ми можемо бачити це ". каталог також вказує на той самий inode.

797358 drwxr-xr-x 3 mkannan mkannan 4096 Sep 17 19:13 a

І тут ми можемо виявити, що каталог "a" має три жорстких посилання. Це тому, що в inode 797358 є три тверді посилання на ім'я ". всередині каталогу "a" і назвіть як ".." всередині каталогу "b" і одне з ім'ям "a" itlef.

$ ls -ali a/
797358 drwxr-xr-x 3 mkannan mkannan 4096 Sep 17 19:13 .

$ ls -ali a/b/
797358 drwxr-xr-x 3 mkannan mkannan 4096 Sep 17 19:13 ..

Тож тут ми можемо зрозуміти, що жорсткі посилання існують лише для каталогів, які з'єднуються з їхніми батьками та дочірніми каталогами. І тому каталог без дитини матиме лише 2 жорстких посилання, і тому каталог "b" матиме лише два жорстких посилання.

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

Оскільки файлова система організована як дерево і оскільки дерево не може мати циклічного посилання, цього слід уникати.


1
Хороший приклад. Це очистило мої сумніви. Тож ці справи обробляються особливим чином, щоб уникнути нескінченних петель. правильно?
G Gill

1
Оскільки у нас обмежений спосіб дозволити жорсткі посилання для каталогів, тобто ".." і "." ми не дійдемо до нескінченного циклу, і тому нам не знадобиться особливих способів уникнути таких, оскільки вони не трапляться :)
Каннан Мохан

5

Жодне з наступного не є реальною причиною заборони жорстких посилань на каталоги; кожну проблему вирішити досить просто:

  • цикли в структурі дерева викликають утруднене обхід
  • багато батьків, тож який "справжній"?
  • збирання сміття файлової системи

Реальна причина (як натякають @ Турбьерн Равн Andersen) приходить , коли ви видаліть каталог , який має кілька батьків, з каталогу , на який вказує ..:

На що ..зараз слід вказувати?

Якщо каталог видалено з його батьківського, але кількість посилань все ж більша, ніж 0тоді, щось має бути, десь все ще вказує на нього. Ви не можете залишити ..вказівку на нічого; багато програм розраховують .., тому системі доведеться пройти всю файлову систему, поки не знайде перше, що вказує на видалений каталог, просто оновити ... Або це, або файлова система повинна була б підтримувати список усіх каталогів, що вказують на жорстко пов'язаний каталог.

Так чи інакше, це буде накладні показники продуктивності та додаткове ускладнення для метаданих файлової системи та / або коду, тому дизайнери вирішили не допустити цього.


3
Це також легко вирішити: зберігайте список батьків дочірнього каталогу, який ви оновлюєте, додаючи або видаляючи посилання на дитину. Коли ви видалите канонічного батька (ціль дитини ..), оновіть, ..щоб вказати на одного з інших батьків у списку.
jathd

2
Я згоден. Не ракетна наука для вирішення. Але, тим не менш, продуктивність накладні, і це займе трохи додаткового місця у метаданих файлової системи та додасть ускладнення. І тому дизайнери пішли на простий, швидкий підхід - не допускайте посилань на жорсткі каталоги.
Lqueryvg

1
Посилання Sym до dirs "порушують усталену семантику та поведінку", але вони все ще дозволені. Тому для деяких команд потрібні параметри, щоб контролювати, чи дотримуються посилання sym (наприклад, -L у пошуку та cp). Коли програма слідує за "..", виникає подальша плутанина, отже, різниця у виході з pwd та / bin / pwd після проходження символьного зв'язку. Немає "відповідей Unix"; просто дизайнерські рішення. Це обертається навколо того, що стає "..", як я вже заявив у своїй відповіді. На жаль, ".." навіть не згадується у відповіді, що всі інші так завзято голосують.
Lqueryvg

До речі, я не кажу, що я за тверді посилання на пани. Зовсім ні. Я не хочу, щоб моя щоденна робота була складнішою, ніж це вже є.
Lqueryvg

Це не те, що говорить POSIX, але IMO ".." ніколи не повинен був бути концепцією файлової системи, а синтаксично вирішуватись на шляхах, так що a/..це завжди означало б .. Ось як працюють URL-адреси, btw. Це браузер, який вирішує "..", перш ніж він навіть потрапить на сервер. І це чудово працює.
ybungalobill

3

Створення жорстких посилань у каталогах було б незворотним. Припустимо, у нас є:

/dir1
├──this.txt
├──directory
│  └──subfiles
└──etc

Я твердо пов'язую це /dir2.

Так що /dir2тепер також містяться всі ці файли та каталоги

Що робити, якщо я передумав? Я не можу просто rmdir /dir2(тому що це не порожньо)

І якщо я рекурсивно видаляю в /dir2..., це буде також видалено /dir1!

ІМХО - це значною мірою достатня причина уникнути цього!

Редагувати:

Коментарі пропонують видалити каталог, зробивши rmйого. Але rmв не порожньому каталозі виходить з ладу, і така поведінка повинна залишатися, незалежно від того, каталог є жорстким посиланням чи ні. Таким чином, ви не можете просто rmвідключити його. Для цього знадобиться новий аргумент rm, просто сказати, "якщо в inode каталогу є номер посилання> 1, то тільки від'єднайте каталог".

Що, в свою чергу, порушує ще один принцип найменшого здивування: це означає, що видалення щойно створеного мною жорсткого посилання каталогів - це не те саме, що видалення звичайного жорсткого посилання на файл ...

Я перефразую своє речення: Без подальшої розробки створення жорсткого посилання було б незворотним (оскільки жодна поточна команда не могла б обробити видалення, не будучи невідповідною поточній поведінці)

Якщо ми дозволимо більше розробити для вирішення справи, кількість підводних каменів та ризик втрати даних, якщо ви недостатньо знаєте, як працює система, така подія має на увазі, є IMHO достатнім приводом для обмеження жорстких посилань на каталоги.


Це не повинно бути проблемою. У вашому випадку, коли ми створюємо жорстке посилання на dir2, ми мусимо зробити жорстке посилання на весь вміст у dir1, і тому, якщо ми перейменовуємо або видалимо dir2, видаляється лише додаткове посилання на вклад. І це не повинно впливати на dir1 та його вміст, оскільки існує принаймні одне посилання (dir1) до inode.
Каннан Мохан

3
Ваш аргумент невірний. Ви просто від’єднаєте це, а не робити rm -rf. І якщо кількість посилань досягне 0, система знає, що також може видалити весь вміст.
LtWorf

Це більш-менш все rmробить під будь-яким чином (від’єднання). Дивіться: unix.stackexchange.com/questions/151951/… Це справді не проблема, не більше, ніж із файлами з твердими посиланнями. Відміняння зв’язку просто видаляє названий посилання та зменшує кількість посилань. Те, що rmdirне видалятиме непорожні каталоги, не має значення - це не зробило б жодного з dir1 них. Жорсткі посилання не є копіями даних, вони є тим самим фактичним файлом, отже, фактично "видалення" файлу dir2 видалить список каталогів для dir1. Вам завжди потрібно буде від’єднати зв’язок.
BryKKan

Ви не можете просто від’єднати його як звичайний файл, тому що rmв каталозі не від’єднуйте його, якщо він не порожній. Див. Редагувати.
П’єр-Олів'є Варес

1

Це хороше пояснення. Щодо "На кого з декількох батьків слід .. вказувати?" одним із рішень було б процес, щоб підтримувати свій повний шлях wd, або як inodes, або як рядок. inodes було б більш надійним, оскільки назви можна змінювати. Принаймні, за старих часів існував вбудований inode для кожного відкритого файлу, який збільшувався щоразу, коли файл відкривався, зменшувався при закритті. Коли він досягне нуля, і сховище, на яке він вказував, буде звільнене. Коли файл більше ніхто не відкривав, він (Основна копія) буде залишений. Це дозволило б підтримувати шлях як дійсний, якщо якийсь інший процес перемістив каталог в інший каталог, поки підкаталог знаходився в шляху іншого процесу. Подібно до того, як можна видалити відкритий файл, але він просто видаляється з каталогу,

Каталоги з твердими посиланнями, які раніше були вільно дозволені в Bell Labs UNIX, принаймні V6 та V7, Не знаю про Берклі чи пізніші версії. Не потрібно прапор. Не могли б ви зробити петлі? Так, не робіть цього. Цілком зрозуміло, що ти робиш, якщо робиш цикл. Нічого, якщо ви будете практикувати зав'язування вузла на шиї, поки ви чекаєте своєї черги, щоб скакати з літака, якщо інший кінець зручно висить з гачка на об'ємній голові.

Що я сподівався зробити з цим сьогодні, це налагодити жорстке з'єднання lhome до дому, щоб я міг мати доступ до дому / адміністрування, незалежно від того, чи / home був прикритий автоматичним режимом роботи над домом, що automount має символьне посилання на ім'я Administ to / lhome / адмін. Це дозволяє мені мати адміністративний акаунт, який працює незалежно від стану моєї основної домашньої файлової системи. Це IS експеримент для Linux, але я думаю, свого часу дізнався для UOS на базі UCB SunOS про те, що автоматичні автомати виконуються на рівні рядка ascii. Важко зрозуміти, як вони могли бути зроблені в іншому випадку як шар поверх будь-якого довільного ФС.

Я читав деінде це. і .. - теж не файли в каталозі. Я впевнений, що для цього є вагомі причини, і багато чого з того, що нам подобається (наприклад, змогти встановити NTFS), можливо через такі речі, але деякі елегантності UNIX були в реалізації. Саме такі переваги, як загальність та ковкість, забезпечували ця елегантність, що дало їй змогу бути настільки міцною та витримати протягом чотирьох десятиліть. Коли ми втрачаємо елегантні реалізації, вони з часом стануть схожими на Windows (сподіваюся, я помиляюся!). Потім хтось створить нову ОС, яка базується на елегантних принципах. Щось подумати. Можливо, я помиляюся, я (очевидно) не знайомий з нинішньою реалізацією. Це є дивовижно, але наскільки застосовно 30-річне розуміння для Linux ... більшість часу!


Я думаю, хоча я можу помилятися, .але ..це не є жорсткими посиланнями у файловій системі, але для сучасних файлових систем. Однак драйвер файлової системи підробляє їх. Саме ці файлові системи зупиняють вікна жорсткого посилання каталогів. Для старих файлових систем це було можливо (але небезпечно). Щоб робити те, що ви намагаєтеся, подивіться mount --bind, побачите також mount --make…і, можливо, контейнери.
ctrl-alt-delor

0

З того, що я збираю, головна причина полягає в тому, що корисно мати можливість змінювати імена каталогів, не псуючи запущені програми, які використовують їх робочий каталог для посилання на інші файли. Припустимо, ви використовували Wine для запуску ~/.newwineprefix/drive_c/Program Files/Firefox/Firefox.exe, і ви хотіли ~/.wineзамість цього перемістити весь префікс . Якщо з якихось дивних причин Firefox отримав доступ drive_c/windows, посилаючись на ../../windows, перейменування ~/.newwineprefixперериває реалізацію, ..що відстежує батьківський каталог як текстовий рядок замість inode.

Зберігання inode одного батьківського каталогу повинно бути простішим, ніж намагатися відслідковувати кожен шлях, як текстовий рядок, так і ряд вкладень.

Ще одна причина полягає в тому, що недобросовісні програми можуть створювати петлі. Програми, що ведуть себе, повинні мати можливість перевіряти, чи вкладеність переміщеної каталоги збігається з inode будь-якого з вкладених каталогів, в які вона переміщується, так само як ви не можете перемістити каталог у себе, але це може бути не застосовано на рівні файлової системи.

Ще одна причина може полягати в тому, що якби ви могли жорстко посилатися на каталоги, ви хочете запобігти жорсткому посиланню на каталог, який ви не могли змінити. findмає міркування щодо безпеки, оскільки він використовується для очищення файлів, створених іншими користувачами з тимчасових каталогів, що може спричинити проблеми, якщо користувач переключить реальний каталог на симпосилання, одночасно findвикликаючи іншу команду. Можливість жорсткого посилання на важливі каталоги змусить адміністратора додати додаткові тести, findщоб уникнути їх впливу. (Гаразд, ви вже не можете цього зробити для файлів, тому ця причина недійсна.)

Ще одна причина полягає в тому, що зберігання inode батьківського каталогу може забезпечити зайву надмірність у випадку пошкодження або пошкодження файлової системи. Якщо ви хотіли ..перерахувати всі батьківські каталоги, які жорстко посилаються на цей, тож інший, довільний батьків може бути легко знайдений, якщо поточний вилучений, ви не тільки порушуєте думку про те, що жорсткі посилання рівні, ви повинні змінити, як файлова система зберігає та використовує inode. Якщо програми трактують шляхи як ряд (унікальний для кожного твердого посилання) індексів каталогів, цього б уникнути, але ви не отримаєте надмірність у випадку пошкодження файлової системи.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.