UNIX / Linux에서 디렉토리에 대한 하드 링크가 허용되지 않는 이유는 무엇입니까? 링크를 만들면 얼마 후에 원본 파일을

유닉스 / 리눅스는 디렉토리에 대한 하드 링크는 허용하지 않지만 소프트 링크는 허용한다는 교재를 읽었습니다. 주기가 있고 하드 링크를 만들면 얼마 후에 원본 파일을 삭제하면 가비지 값을 가리 키기 때문입니까?

사이클이 하드 링크를 허용하지 않는 유일한 이유라면 디렉토리에 대한 소프트 링크가 허용되는 이유는 무엇입니까?



답변

하드 링크와 원래 이름의 차이점을 구분할 방법이 없기 때문에 이것은 나쁜 생각입니다.

디렉토리에 대한 하드 링크를 허용하면 파일 시스템의 지시 된 비순환 그래프 구조가 깨져 디렉토리 루프가 생성되고 디렉토리 서브 트리가 매달려있을 수 fsck있으며 다른 파일 트리 워커에서 오류가 발생하기 쉽습니다.

먼저 이것을 이해하기 위해 inode에 대해 이야기합시다. 파일 시스템의 데이터는 디스크의 블록에 보관되며 이러한 블록은 inode에 의해 함께 수집됩니다. inode를 THE 파일로 생각할 수 있습니다. 그러나 아이 노드는 파일 이름이 없다. 그것이 링크가 들어오는 곳입니다.

링크는 단지 inode에 대한 포인터입니다. 디렉토리는 링크를 보유하는 inode입니다. 디렉토리의 각 파일 이름은 inode에 대한 링크 일뿐입니다. 유닉스에서 파일을 열면 링크도 생성되지만 다른 유형의 링크입니다 (이름이 지정된 링크가 아님).

하드 링크는 해당 inode를 가리키는 추가 디렉토리 항목입니다. 의 ls -l경우 권한 뒤의 숫자는 명명 된 링크 수입니다. 대부분의 일반 파일에는 하나의 링크가 있습니다. 파일에 새로운 하드 링크를 만들면 두 파일 이름이 모두 동일한 inode를 가리 킵니다. 노트 :

% 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, 어떤 파일이 원본 파일이고 어떤 파일이 하드 링크입니까? 결국 두 이름이 동일한 내용, 동일한 inode를 가리 키기 때문에 실제로 (타임 스탬프조차도) 알 수 없습니다.

% 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

행의 시작 부분에 inode 번호 -ils표시 하는 플래그 입니다. 어떻게 주 testtest2같은 inode 번호를 가지고 있지만, test3다른 하나가 있습니다.

이제 디렉토리에 대해이 작업을 수행 할 수 있으면 파일 시스템의 다른 지점에있는 두 개의 다른 디렉토리가 동일한 것을 가리킬 수 있습니다. 실제로, 하위 디렉토리는 조부모를 다시 가리키면서 루프를 만들 수 있습니다.

이 루프가 왜 문제가 되나요? 트래버스를 할 때는 루핑을 감지 할 수있는 방법이 없기 때문에 트래버스 할 때 inode 번호를 추적하지 않아도됩니다. du디스크 사용에 대해 알아 보려면 하위 디렉토리를 통해 반복해야하는 명령을 작성한다고 가정하십시오 . du루프에 언제 도달하는지 어떻게 알 수 있습니까? du이 간단한 작업을 시작 하기 위해서는 오류가 발생하기 쉽고 많은 부기 가 필요합니다.

심볼릭 링크는 많은 파일 파일 시스템 API가 자동으로 따르는 경향이있는 특수한 유형의 “파일”이라는 점에서 완전히 다릅니다. 심볼릭 링크는 존재하지 않는 대상을 가리킬 수 있습니다. 즉, inode를 직접 가리키는 것이 아니라 이름을 가리 킵니다. “하드 링크”라는 단순한 존재는 파일이 존재한다는 것을 의미하기 때문에이 개념은 하드 링크에서는 의미가 없습니다.

그렇다면 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    .


답변

마운트 지점을 제외하고 각 디렉토리에는 하나의 상위 디렉토리 만 ..있습니다.

한 가지 방법 pwd은 장치를 확인하는 것입니다. 그리고 ‘..’. 동일하면 파일 시스템의 루트에 도달 한 것입니다. 그렇지 않으면 부모에서 현재 디렉토리의 이름을 찾아서 스택에 넣고 ‘../.’비교를 시작하십시오. ‘../ ..’, ‘../../.’ ‘../../ ..’등을 사용하십시오. 루트에 도달하면 스택에서 이름을 터 뜨리고 인쇄를 시작하십시오. 이 알고리즘은 각 디렉토리에 하나의 상위 디렉토리 만 있다는 사실에 의존합니다.

디렉토리에 대한 하드 링크가 허용 된 경우 여러 부모 중 하나를 ..가리켜 야 합니까? 이것이 디렉토리에 대한 하드 링크가 허용되지 않는 강력한 이유 중 하나입니다.

디렉토리에 대한 심볼릭 링크는 그 문제를 일으키지 않습니다. 프로그램이 원하는 경우 lstat()경로 이름의 각 부분에 대해 수행 하고 심볼릭 링크가 발생할 때를 감지 할 수 있습니다. pwd알고리즘은 대상 디렉토리를 진정한 절대 경로를 반환합니다. 대상 디렉토리를 가리키는 텍스트 (심볼릭 링크)가 있다는 사실은 거의 관련이 없습니다. 이러한 심볼릭 링크가 존재하더라도 그래프에 루프가 생성되지 않습니다.


답변

바인드 마운트를 사용하여 하드 링크 디렉토리를 시뮬레이션 할 수 있습니다.

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


답변

이 질문에 대한 몇 가지 요점을 추가하고 싶습니다. 디렉토리에 대한 하드 링크는 리눅스에서 허용되지만 제한된 방식으로 허용됩니다.

이를 테스트 할 수있는 한 가지 방법은 디렉토리의 내용을 나열 할 때 두 개의 특수 디렉토리 “를 찾는 것입니다.” 그리고 “..”. 우리가 알다시피 “.” 동일한 디렉토리를 가리키고 “..”는 상위 디렉토리를 가리 킵니다.

“a”는 “b”디렉토리를 자식 디렉토리로하는 부모 디렉토리입니다.

 a
 `-- b

디렉토리 “a”의 inode를 기록해 두십시오. 그리고 ls -lafrom 디렉토리 “a”를하면 “.”를 볼 수 있습니다. 디렉토리도 동일한 inode를 가리 킵니다.

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

그리고 여기서 “a”디렉토리에는 세 개의 하드 링크가 있습니다. 이는 inode 797358에 “.”이라는 이름의 세 개의 하드 링크가 있기 때문입니다. “a”디렉토리 내부에 “..”디렉토리 이름 “b”내부에 이름 “a”가있는 파일 이름

$ 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”디렉토리에는 2 개의 하드 링크 만 있습니다.

디렉토리의 하드 링크가 자유롭게 금지되는 한 가지 이유는 파일 시스템을 순회하는 프로그램을 혼란스럽게하는 무한 참조 루프를 피하는 것입니다.

파일 시스템이 트리로 구성되고 트리가 순환 참조를 가질 수 없으므로 이것은 피해야합니다.


답변

다음 중 디렉토리에 대한 하드 링크를 허용하지 않는 실질적인 이유는 없습니다. 각 문제는 해결하기가 상당히 쉽습니다.

  • 트리 구조의주기는 통과를 어렵게합니다
  • 여러 부모, 그래서 “진짜”하나?
  • 파일 시스템 가비지 수집

진짜 이유 (@ Thorbjørn Ravn 안데르센 암시로)는 때 오는 삭제 디렉토리가 가리키는에서 여러 부모가있는 디렉토리를 ..:

..이제 무엇을 가리켜 야 합니까?

디렉토리가 상위 디렉토리에서 삭제되었지만 링크 수가 여전히 크면 링크 0가있는 곳이 있어야합니다. ..아무 것도 가리 키지 않을 수 없습니다 . 많은 프로그램이 의존 ..하기 때문에 시스템은 삭제 된 디렉토리를 가리키는 첫 번째 항목을 찾을 때까지 전체 파일 시스템 을 순회 해야합니다 ... 또는 파일 시스템은 하드 링크 된 디렉토리를 가리키는 모든 디렉토리의 목록을 유지해야합니다.

어느 쪽이든, 이것은 파일 시스템 메타 데이터 및 / 또는 코드에 대한 성능 오버 헤드추가 복잡성 일 수 있으므로 설계자는 허용하지 않기로 결정했습니다.


답변

디렉토리에서의 하드 링크 생성은 되돌릴 수 없습니다. 우리가 가지고 있다고 가정 해보십시오.

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

에 하드 링크했습니다 /dir2.

그래서 /dir2이제 모든 파일과 디렉토리를 포함

마음이 바뀌면 어떻게해야합니까? 나는 단지 rmdir /dir2비어 있지 않기 때문에 할 수 없다.

그리고 재귀 적으로 삭제하면 /dir2…에서도 삭제됩니다 /dir1!

IMHO 이것을 피할 수있는 충분한 이유입니다!

편집하다 :

의견은 디렉토리를 제거하여 디렉토리를 제거하도록 제안 rm합니다. 그러나 rm비어 있지 않은 디렉토리에서 실패하면 디렉토리의 하드 링크 여부에 관계없이이 동작이 남아 있어야합니다. 따라서 rm연결을 해제 할 수는 없습니다 . rm“디렉토리 inode의 참조 수가> 1이면 디렉토리의 링크 만 해제하십시오” 라는 새 인수가 필요합니다 .

차례로, 놀랍게도 다른 원칙을 깨십시오. 방금 만든 디렉토리 하드 링크를 제거하는 것이 일반 파일 하드 링크를 제거하는 것과 동일하지 않다는 것을 의미합니다 …

나는 나의 문장을 다시 말할 것이다 : 더 이상의 개발이 없다면, 하드 링크 생성은 되돌릴 수 없을 것이다 (현재의 명령이 현재의 행동과 일치하지 않고 제거를 처리 할 수 ​​없기 때문에)

우리가 더 많은 개발을 통해 사건을 처리 할 수있게한다면 , 시스템이 어떻게 작동하는지에 대해 충분히 알지 못하는 경우 함정 수와 데이터 손실 위험이 발생 합니다. 이러한 개발에서 암시하는 것은 IMHO가 디렉토리에서 하드 링크를 제한하는 충분한 이유입니다.


답변

이것은 좋은 설명입니다. “여러 부모 중 한 명은 어느 쪽을 가리켜 야합니까?” 한 가지 해결책은 프로세스가 전체 wd 경로를 inode 또는 문자열로 유지하는 것입니다. 이름을 변경할 수 있으므로 inode가 더 강력 해집니다. 적어도 옛날에는 파일을 열 때마다 증가하고 닫을 때 감소한 모든 열린 파일에 대해 코어 내 inode가있었습니다. 그것이 0에 도달하면 스토리지가 해제됩니다. 다른 사람이 파일을 더 이상 열지 않으면 파일 (In-Core 사본)은 버려집니다. 서브 디렉토리가 다른 프로세스의 경로에있는 동안 다른 프로세스가 디렉토리를 다른 디렉토리로 이동 한 경우 경로를 유효한 것으로 유지합니다. 열린 파일을 삭제하는 방법과 비슷하지만 디렉토리에서 간단히 제거됩니다.

Bell Labs UNIX (최소 V6 및 V7)에서는 하드 링크 디렉토리를 자유롭게 사용할 수있었습니다. Berkeley 이상은 모릅니다. 플래그가 필요하지 않습니다. 루프를 만들 수 있습니까? 그렇습니다. 루프를 만들면 현재하고있는 일이 매우 분명합니다. 다른 쪽 끝이 벌크 헤드의 고리에 매달려 있으면 목에서 매듭 묶기를 연습해야합니다.

무엇 나는 오늘 내가 / 집 / 여부를 사용할 수 administ을 가질 수 있도록 / 가정, 가정 통해 automout로 / lhome에 심볼릭 링크라는 이름의 administ을 갖는 자동 마운트를 덮고 집에 하드 링크 lhome이었다 함께 할 희망 / 관리자. 이를 통해 기본 홈 파일 시스템의 상태에 관계없이 작동하는 관리 계정을 가질 수 있습니다. 이것은 IS 리눅스에 대한 실험,하지만 난 자동 마운트는 ASCII 문자열의 수준에서 수행된다는 UCB 기반 SunOS의 위해 한 번에 배운 생각합니다. 임의의 FS 위에서 레이어로 어떻게 수행 될 수 있는지 알기가 어렵습니다.

나는 다른 곳에서 읽었다. 그리고 ..도 더 이상 디렉토리에 파일이 아닙니다. 나는이 모든 것들에 대한 충분한 이유가 있다고 확신하며, NTFS로 마운트 할 수있는 것과 같은 것들 때문에 이런 것들이 가능하지만 UNIX의 우아함은 구현에있었습니다. 이 우아함이 제공하는 일반 성과 가단성과 같은 이점은 40 년 동안 견고하고 견딜 수있게 해줍니다. 우리가 우아한 구현을 풀면 결국 Windows와 같아 질 것입니다. 그런 다음 누군가는 우아한 원칙에 기반한 새로운 OS를 만들 것입니다. 생각할 것. 어쩌면 나는 틀렸다. 현재 구현에 익숙하지 않다. 그것은 이다 30 년 된 이해가 리눅스에 얼마나 적용 가능한지 놀라운 데 … 대부분의 경우!