리눅스의 모든 것이 파일이라면 디렉토리는 무엇인가? 문구를 자주 듣습니다. 그러나 디렉토리는 무엇입니까?

초보자는 “Linux / Unix의 모든 파일”이라는 문구를 자주 듣습니다. 그러나 디렉토리는 무엇입니까? 파일과 어떻게 다릅니 까?



답변

참고 : 원래 이것은 명령 의 현재 디렉토리 ls가 자신과 연결된 것으로 식별되는 이유에 대한 내 대답을 지원하기 위해 작성되었습니다 . 그러나 나는 이것이 독자적으로 견딜 가치가있는 주제이며 따라서이 Q & A라고 느꼈습니다 .

유닉스 / 리눅스 파일 시스템 및 파일 이해 : 모든 것이 inode입니다

기본적으로 디렉토리는 항목 목록과 해당 ID를 포함하는 특수 파일 일뿐입니다.

토론을 시작하기 전에 몇 가지 용어를 구별하고 디렉토리와 파일이 실제로 무엇을 나타내는 지 이해하는 것이 중요합니다. 유닉스 / 리눅스에서 “Everything is a file”이라는 표현을 들어 보셨을 것입니다. 사용자가 파일로 자주 이해하는 것은 다음과 같습니다 /etc/passwd.-경로와 이름 이 있는 객체. 실제로 이름 (디렉토리 또는 파일 등)은 텍스트의 문자열 일 뿐이며 실제 객체의 속성입니다. 이 객체를 inode 또는 I- 번호 라고 하며 inode 테이블의 디스크에 저장합니다. 개방형 프로그램에도 아이 노드 테이블이 있지만, 지금은 우리의 관심사가 아닙니다.

디렉토리에 대한 유닉스의 개념은 켄 톰슨이 1989 년 인터뷰 에서 언급 한 내용이다 .

… 그리고 그 파일 중 일부는 이름과 I- 번호를 포함하는 디렉토리였습니다.

흥미로운 관찰에서 만들어 질 수 는 1972 년 데니스 리치의 이야기

“… 디렉토리는 실제로 파일에 지나지 않지만 그 내용은 시스템에 의해 제어되며 그 내용은 다른 파일의 이름입니다 (디렉토리는 다른 시스템에서 카탈로그라고도 함).”

…하지만 대화의 어느 곳에서나 inode에 대한 언급은 없습니다. 그러나 1971 년 매뉴얼format of directories다음과 같습니다.

파일이 디렉토리라는 사실은 i- 노드 항목의 플래그 단어에 비트로 표시됩니다.

디렉토리 항목의 길이는 10 바이트입니다. 첫 단어는 0이 아닌 경우 항목으로 표시되는 파일의 i 노드입니다. 0이면 항목이 비어 있습니다.

그래서 처음부터 존재했습니다.

디렉토리와 inode 쌍화는 디렉토리 구조가 UNIX 파일 시스템에 어떻게 저장됩니까?에서 설명합니다 . . 디렉토리 자체는보다 구체적으로 데이터 구조입니다. 즉, 해당 객체 (권한, 유형, 소유자, 크기 등)에 대한 목록을 가리키는 객체 (파일 및 inode 번호) 목록입니다. 따라서 각 디렉토리에는 고유 한 inode 번호와 파일 이름 및 inode 번호가 있습니다. 가장 유명한 것은 디렉토리 인 inode # 2입니다/ . 그 불구하고 (주, /dev/run가상 파일 시스템들이 자신의 파일 시스템에 대한 루트 폴더가 너무 때문에,있다, 그들은 또한 두 아이 노드가; 즉, inode는 자체 파일 시스템에서 고유하지만 여러 파일 시스템이 연결되어 있으면 고유하지 않은 inode가 있습니다). 관련 질문에서 빌린 다이어그램은 아마도 간결하게 설명 할 것입니다.

stat()Linux 에 따라 inode에 저장된 모든 정보는 시스템 호출을 통해 액세스 할 수 있습니다 man 7 inode.

각 파일에는 파일에 대한 메타 데이터가 포함 된 inode가 있습니다. 애플리케이션은 stat 구조를 리턴하는 stat (2) (또는 관련 호출) 또는 statx 구조를 리턴하는 statx (2)를 사용하여이 메타 데이터를 검색 할 수 있습니다.

inode 번호 ( ref1 , ref2 ) 만 알고있는 파일에 액세스 할 수 있습니까? 일부 유닉스 구현에서는 가능하지만 권한 및 액세스 검사를 무시하므로 Linux에서는 구현되지 않으며 파일 시스템 트리를 통과하여 파일 find <DIR> -inum 1234이름과 해당 inode를 가져와야합니다.

소스 코드 레벨에서는 Linux 커널 소스에 정의되어 있으며 ext3 및 ext4 파일 시스템 (Ubuntu 기본값)을 포함하여 Unix / Linux 운영 체제에서 작동하는 많은 파일 시스템에서도 채택됩니다. 흥미로운 점 : 데이터는 단지 정보 블록 일 뿐이 므로 리눅스는 실제로 inode가 파이프 ( inode->i_pipe) 인지 확인할 수있는 inode_init_always 기능 을 가지고 있습니다 . 예, 소켓과 파이프는 기술적으로도 파일입니다. 익명 파일이며 디스크에 파일 이름이 없을 수 있습니다. FIFOUnix-Domain 소켓 에는 파일 시스템에 파일 이름이 있습니다.

데이터 자체는 고유 할 수 있지만 inode 번호는 고유하지 않습니다. foobar라는 foo에 대한 하드 링크가 있다면 inode 123도 가리킬 것입니다. 이 inode 자체에는 해당 inode가 차지하는 실제 디스크 공간 블록에 대한 정보가 들어 있습니다. 이것이 기술적으로 .디렉토리 파일 이름에 연결되는 방법 입니다. 음, 거의 : 리눅스 자신의 디렉토리에 하드 링크를 만들 수 있지만, 파일 시스템 만 갖는 제약 만드는 매우 훈련 방법의 디렉토리에 하드 링크 할 수 있습니다 ...하드 링크 등을.

디렉토리 트리

파일 시스템은 디렉토리 트리를 트리 데이터 구조 중 하나로 구현합니다. 특히,

  • ext3 및 ext4는 HTree를 사용합니다
  • xfs는 B + Tree를 사용합니다
  • zfs는 해시 트리를 사용합니다

여기서 핵심은 디렉토리 자체가 트리의 노드이고 하위 디렉토리는 하위 노드이며 각 하위는 상위 노드에 대한 링크를 갖습니다. 따라서 디렉토리 링크의 경우 베어 디렉토리 (디렉토리 이름 /home/example/에 링크 및 self에 링크)의 inode 수는 최소 2 /home/example/.이며 각 추가 서브 디렉토리는 추가 링크 / 노드입니다.

# 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
# Count of links for root
$ stat --format=%h /
25
# Count of subdirectories, minus .
$ find / -maxdepth 1 -type d | wc -l
24

에서 발견 된 그림 이안 D. 알렌의 코스 페이지 쇼 단순화 아주 명확한 그림 :

WRONG - names on things      RIGHT - names above things
=======================      ==========================

    R O O T            --->         [etc,bin,home]   <-- ROOT directory
   /   |   \                         /    |      \
etc   bin   home       --->  [passwd]  [ls,rm]  [abcd0001]
 |   /   \    \                 |      /    \       |
 |  ls   rm  abcd0001  --->     |  <data>  <data>  [.bashrc]
 |               |              |                   |
passwd       .bashrc   --->  <data>                <data>

RIGHT 다이어그램에서 올바르지 않은 유일한 것은 파일이 기술적으로 디렉토리 트리 자체에있는 것으로 간주되지 않는다는 것입니다. 파일을 추가해도 링크 수에는 영향을 미치지 않습니다.

$ mkdir subdir2
$ stat --format=%h .
4
# Adding files doesn't make difference
$ cp /etc/passwd passwd.copy
$ stat --format=%h .
4

마치 파일 인 것처럼 디렉토리에 액세스

Linus Torvalds 를 인용하려면 :

“모든 것이 파일입니다”의 요점은 임의의 파일 이름을 가지고 있지 않다는 것입니다 (실제로 소켓과 파이프는 “파일”과 “파일 이름”이 서로 관련이 없음을 보여줍니다). 다른 것들에서 작동하는 도구.

디렉토리는 파일의 특별한 경우라는 점을 고려하면 당연히 일반 파일과 비슷한 방식으로 파일 을 열고 , 읽고 , 쓰고 , 닫을 수있는 API가 있어야 합니다.

그것이 dirent.hC 라이브러리가있는 곳이며, man 3 readdirdirent 에서 찾을 수 있는 구조 를 정의합니다 :

   struct dirent {
       ino_t          d_ino;       /* Inode number */
       off_t          d_off;       /* Not an offset; see below */
       unsigned short d_reclen;    /* Length of this record */
       unsigned char  d_type;      /* Type of file; not supported
                                      by all filesystem types */
       char           d_name[256]; /* Null-terminated filename */
   };

따라서 C 코드에서을 정의 struct dirent *entry_p하고로 디렉토리를 열고 opendir()읽을 때 readdir()각 항목을 해당 entry_p구조에 저장합니다 . 물론 각 항목에는 dirent위에 표시된 템플리트에 정의 된 필드가 포함됩니다 .

이것이 어떻게 작동하는지에 대한 실제적인 예 는 현재 작업 디렉토리에 파일과 파일의 inode 번호를 나열하는 방법에 대한 나의 대답에서 찾을 수 있습니다 .

fdopenPOSIX 매뉴얼 은 “점과 점에 대한 디렉토리 항목은 선택 사항”이라고 말하고 readdir 수동 상태 struct direntd_named_ino필드 에만 필요 합니다.

디렉토리에 “쓰기”에 대한 참고 사항 : 디렉토리에 쓰기는 “항목 목록”을 수정합니다. 따라서 파일 작성 또는 제거는 디렉토리 쓰기 권한 과 직접 연관되며 파일 추가 / 제거는 해당 디렉토리에 대한 쓰기 조작입니다.