파일은 정확히 어떻게 내부에 보관되나요? [폐쇄]

파일은 정확히 어떻게 내부에 보관되나요? [폐쇄]

내가 아는 한, 파일의 inode가 발견되면 데이터를 찾는 것은 간단합니다. inode에 저장된 디스크의 특정 위치에 액세스하면 됩니다.

그런데 문제는 시스템에 파일 경로가 주어지면 도대체 어떻게 인덱스 노드를 찾는 걸까요?

내 질문의 목적은 주로 B-트리가 실제 생활에서 어떻게 구현되는지 이해하는 것입니다. 나는 그것의 일반적인 아이디어를 이해하지만 그것이 Unix 파일 시스템에서 정확히 어떻게 구현되는지 (만약 있다면) 알고 싶습니다.

트리의 각 노드는 inode 번호를 저장하고, 리프도 inode 자체의 디스크 주소를 저장합니까? 아니면 파일 경로의 연속된 부분일까요?

디스크가 하드 드라이브인지 SSD인지에 따라 구현이 달라지나요?

답변1

IMHO: 두 가지 질문이 있습니다:

시스템에 파일 경로를 제공할 때 인덱스 노드를 정확하게 찾는 방법

그리고

B-트리가 실제 생활에서 어떻게 구현되는지 파악하고 싶습니다.

아마도 귀하의 질문은 inode가 어떻게 저장되는지(b-트리에) 또는 inode가 참조하는 데이터일 것입니다. 그렇다면 저는 대답할 수 없습니다.

첫 번째 문자 그대로의 질문에 대한 답변은 운영 체제에 따라 다르며 범위 not difficultopaque. 고전적인 시스템 호출(open, unlink)은 파일 이름 항목을 찾는 디렉토리를 읽고 (현대에서는 opendir()을 호출하여) 시작됩니다.

클래식 UNIX에서 파일 이름의 최대 길이는 14자입니다. 즉, inode용으로 2바이트(디렉토리 항목용으로 16바이트)가 남습니다. 파일 이름과 inode의 b-트리 구성은 없었습니다(그리고 여전히 그렇습니다). 검색은 디렉토리의 연속 읽기였습니다(그리고 지금도 그렇습니다). 이는 simple반드시 확인해야 할 사항입니다.

더 긴 파일 이름을 허용하는 오늘날의 시스템에서도 디렉토리 항목의 기본 모양은 변경되지 않을 수 있습니다(2바이트(인덱스 노드), 14바이트(초기 파일 이름/전체 파일 이름)). (적어도 AIX에서는 모든 것, 심지어 디렉토리도 UNIX 관용어를 따릅니다. 모든 것이 파일이고 일부는 특별합니다.)

michael@x071:[/home/michael]ls -lia /tmp | head
total 287464
    2 drwxrwxrwt 54 bin      bin       36864 Jan 22 13:35 .
    2 drwxr-xr-x 39 root     system     4096 Jan  5 12:27 ..
    5 drwxrwxrwt  2 root     system      256 May  8  2013 .X11-unix
    6 -rw-r-----  1 root     system        0 May 23  2014 .ahafs.out.michael.10223652
    7 -rw-r-----  1 root     system        0 May 23  2014 .ahafs.out.michael.9502870
    8 -r--r--r--  1 root     system       25 Jun  9  2013 .aix_ISMP_lock____.save
    9 drwxrwxrwt  3 root     system     4096 Dec 27 12:15 .com_ibm_tools_attach
   62 -rw-r--r--  1 root     system     3124 Dec 27 11:21 .ctinst.log
   63 -rw-r-----  1 michael  felt       2578 Aug 16  2013 .htaccess

michael@x071:[/home/michael]od -dc /tmp | head -20
0000000       2   11776       0       0       0       0       0       0
         \0 002   .  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0
0000020       2   11822       0       0       0       0       0       0
         \0 002   .   .  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0
0000040   32848   11895   28530   27492   26994   11825   13109   13878
        200   P   .   w   o   r   k   d   i   r   .   1   3   5   6   6
0000060       5   11864   12593   11637   28265   30720       0       0
         \0 005   .   X   1   1   -   u   n   i   x  \0  \0  \0  \0  \0
0000100       6   11873   26721   26227   11887   30068   11885   26979
         \0 006   .   a   h   a   f   s   .   o   u   t   .   m   i   c
0000120       7   11873   26721   26227   11887   30068   11885   26979
         \0  \a   .   a   h   a   f   s   .   o   u   t   .   m   i   c
0000140       8   11873   27000   24393   21325   20575   27759   25451
         \0  \b   .   a   i   x   _   I   S   M   P   _   l   o   c   k
0000160       9   11875   28525   24425   25197   24436   28527   27763
         \0  \t   .   c   o   m   _   i   b   m   _   t   o   o   l   s
0000200      62   11875   29801   28275   29742   27759   26368       0
         \0   >   .   c   t   i   n   s   t   .   l   o   g  \0  \0  \0
0000220      63   11880   29793   25443   25971   29440       0       0
         \0   ?   .   h   t   a   c   c   e   s   s  \0  \0  \0  \0  \0

참고: 위의 내용은 Linux 시스템에서 시도되었습니다. 아마도 이제 B-트리로 구성되어 있을 것입니다. 모르겠어요. 다음과 같은 결과가 나오거든요.

michael@x067:~$ od -dc /tmp|head
od: /tmp: read error: Is a directory
0000000

따라서 전통적으로 (특수) 파일에 대한 inode "조회/매핑"은 디렉토리 항목의 처음 2바이트에 불과합니다. 인덱스 노드는 디스크에 위치하거나 B-트리와 같은 메모리에 저장됩니다.

AIX에서 'dirent' 구조는 다음 형식으로 "쉽게 찾을 수 있습니다".

#define _D_NAME_MAX 255

struct  dirent {
        __ulong64_t     d_offset;       /* real off after this entry */
        ino_t           d_ino;          /* inode number of entry */
        ushort_t        d_reclen;       /* length of this record */
        ushort_t        d_namlen;       /* length of string in d_name */
        char            d_name[_D_NAME_MAX+1];  /* name must be no longer than this */
                                        /* redefine w/#define when name decided */
};

Linux(3.2.XY 커널)의 경우 포함 파일에는 다음 구조가 포함되어 있습니다.

struct dirent
  {
#ifndef __USE_FILE_OFFSET64
    __ino_t d_ino;
    __off_t d_off;
#else
    __ino64_t d_ino;
    __off64_t d_off;
#endif
    unsigned short int d_reclen;
    unsigned char d_type;
    char d_name[256];           /* We must not include limits.h! */
  };

둘 다(IMHO)는 기본적으로 동일합니다. 반환 시 readdir()을 호출하면 차이점을 제거할 수 있습니다.

Linux/GNU 방법:

/usr/include/dirent.h:
/* This is the data type of directory stream objects.
   The actual structure is opaque to users.  */
typedef struct __dirstream DIR;

참고: __dirstream에 대해 아무것도 찾을 수 없어서 이에 대한 "설명"을 추가했습니다.opaque

extern DIR *opendir (__const char *__name) __nonnull ((1));
...
/* Read a directory entry from DIRP.  Return a pointer to a `struct
   dirent' describing the entry, or NULL for EOF or error.  The
   storage returned may be overwritten by a later readdir call on the
   same DIR stream.

   If the Large File Support API is selected we have to use the
   appropriate interface.

   This function is a possible cancellation point and therefore not
   marked with __THROW.  */
#ifndef __USE_FILE_OFFSET64
extern struct dirent *readdir (DIR *__dirp) __nonnull ((1));
#else
# ifdef __REDIRECT
extern struct dirent *__REDIRECT (readdir, (DIR *__dirp), readdir64)
     __nonnull ((1));
# else
#  define readdir readdir64
# endif
#endif

#ifdef __USE_LARGEFILE64
extern struct dirent64 *readdir64 (DIR *__dirp) __nonnull ((1));
#endif

AIX의 경우:

/*
 * Definitions for library routines operating on directories.
 */
typedef struct _dirdesc {
#ifdef _ALL_SOURCE
        int     dd_fd;          /* file descriptor of directory */
        blksize_t dd_blksize;   /* this filesystem's block size */
        char    *dd_buf;        /* malloc'd buffer depending of fs bsize */
        long    dd_size;        /* size of buffer */
        long    dd_flag;        /* private flags for readdir, unused */
        off_t   dd_loc;         /* logical(dirent) offset in  directory */
        off_t   dd_curoff;      /* real offset in directory corresponding
                                 * to dd_loc */
#else
        int     __dd_fd;                /* file descriptor of directory */
        blksize_t __dd_blksize; /* this filesystem's block size */
        char    *__dd_buf;      /* malloc'd buffer depending of fs bsize */
        long    __dd_size;      /* size of buffer */
        long    __dd_flag;      /* private flags for readdir, unused */
        off_t   __dd_loc;       /* logical(dirent) offset in  directory */
        off_t   __dd_curoff;    /* real offset in directory corresponding
                                 * to dd_loc */
#endif
#if defined(_THREAD_SAFE) && defined(_ALL_SOURCE)
        void    *dd_lock;       /* for inter-thread locking */
#endif

} DIR;

...

extern  DIR *opendir(const char *);
extern  struct dirent *readdir(DIR *);

즉, IMHO는 OS에 따라 구조가 on disk매우 간단하거나 opaque. 커널에서는 opaque애플리케이션 코드를 변경하지 않고도 조직을 수정할 수 있는 조직이라면 놀라지 않을 것입니다.

관련 정보