File Systems - andyceo/documentation GitHub Wiki

Файловые системы

В большинстве посикс-совместимых системах ФС организованы одинаково. Мы будем говорить на примере Linux. Поговорим о том, как примерно организовано хранение файлов в ФС.

  • Понятие файловой системы (ФС)
  • История
  • Устройство
  • Распространенные ФС:
    • FAT/FAT32/exFAT
    • ext2/ext3/ext4
    • reiserfs 3,4
    • NTFS
    • XFS

Что такое файл? Поименованная область данных на диске. Данных может не быть. за файлом может скрываться устройство и т.п. Говоря конкретно, см. описание системного вызова stat: man 2 stat. Этот файл возвращает структуру, которой, с точки зрения ядра, описывается файл.

Структура содержит:

  • id устройства - значит устройств может быть много, жесткий диск, флеш-накопитель и т.п.
  • inode - номер, индексный дескриптор. Каждый файл в пределах своего устройства, однозначно идентифицирован этим номером
  • разрешения доступа - кто имеет право выполнять операции с файлом, + здесь хранится тип файла, в оставшихся разрядах
  • количество ссылок на этот файл. На файл может быть много ссылок одновременно, ссылки - это имена, на самом деле. т.е. файл может иметь несколько разных имен.
  • id пользователя (владелец)
  • id группы (владелец) - в посикс у файла обязательно должна быть группа-владелец
  • id устройства - если этот специальный файл
  • размер. это поле может использоваться для чего-то другого, для спец. файлов, например, имеет два идентификатора - старший и младший номер устройства, кроме этого поля, это некуда положить
  • размер блока (512 байт - это блок файловой системы)
  • количество блоков (сколько блоков занимает файл)
  • время atime (access time) - когда файл открывается, на чтение или запись. логируется время последнего обращения к файлу. например, запустили программу и не знаем, что она делает - можно после ее останова, поискать файлы, у которых время обращения меньше или равно чем, скажем, 30 сек. (7:58) Если обновление времени доступа включено - это снижение производительности - каждый раз при чтении, нужно производить запись. Это контролируется опциями монтирования ФС.
  • время mtime (modify time) - время модификации файловой системы - это то, что мы обычно видим, когда отображается информация о файле
  • время ctime - время изменения статуса. Статус - это метаданные файла. Если файл переименовывается, или на него создается новая ссылка (меняется nlink)

Атрибуты про блоки (размер блока, количество блоков) появились в BSD-системах, и не всегда присутствуют в Linux.

inode

  • Индексный дескриптор
  • Есть у каждого файла
  • «номер» файла
  • Может совпадать у нескольких файлов (жесткая ссылка, каталоги)

Каждый раз, когда создается файл любого типа (обычный, каталог, специальный файл), под него должен быть выделен индексный дескриптор. Количество индексных дескрипторов, которые может иметь ФС, ограничивает количество файлов, которые она может иметь. Некоторые ФС позволяют динамически увеличивать кол-во дескрипторов, но простые (ext2, ext3) имеют фиксированное количество дескрипторов, которое определяется при создании ФС - если вы зададите вручную слишком маленькое значение, то можно получить ситуацию, когда место на ФС еще есть, а файл создать нельзя. Такое бывает в случае множества мелких файлов, особенно нулевого размера. Однако часто бывает так, что файл нулевого размера все равно занимает место на диске, потому что есть расширенные атрибуты, которые хранятся в блоках, а не в метаданных. Чтобы эта ситуация не произошла, при создании ФС автоматически делится размер устройства на размер блока ФС и получается количество дескрипторов. Если мы пожадничали и решили сэкономить (каждый дескриптор занимает какое-то место, 128-256 байт).

Можно посмотреть индексный дескриптор:

stat /etc/passwd

Распределение индексных дескрипторов не обязательно идет подряд.

Поскольку права доступа хранятся вместе с метаданными файла, а не с именем файла, то на все жесткие ссылки у нас одинаковые права доступа. Метаданные не размножаются при создании новых имен файла. Количество ссылок можно посмотреть и через команду ls:

ls -l /etc/passwd

-rw-r--r-- 1 root root 2221 февр. 28 15:46 /etc/passwd

Число 1 после разрешений - это и есть количество ссылок. Возьмем другой файл (16:41):

ls -l /sbin/mkfs.ext2

-rwxr-xr-x 5 root root 55176 сент.  9  2015 /sbin/mkfs.ext2 -> mke2fs

Это утилита, создающая разметку ФС. Как видим у этого файла 5 жестких ссылок. stat подтвердит нам этот вывод. Найдем эти 5 имен:

ls -l /sbin/mkfs.ext* /sbin/mke2fs

Мы имеем дело с программой, которая меняет поведение в зависимости от того, по какому имени ее запустили. Чтобы экономить место на диске, программа хранится в одном экземпляре. Если .ext2 - то создаст файловую систему ext2 и т.п. Основная программа - mke2fs.

st_mode — тип файла

В этом поле закодирован тип файла и его разрешения. См. man 2 stat, поиск 'The following flags are defined for the st_mode field:'.

  • socket (сокет, гнездо) - это UNIX-socket. Создаются через системные вызовы, а не через те операции, которыми создаются обычные файлы. Т.е. нет команды: "создай сокет на ФС", есть системные вызовы. Пример сокета можно наблюдать в работе дисплейного сервера X. Происходит клиент-серверное взаимодействие: эмулятор терминала соединяется по сокету с сервером графического экрана и дает ему команды, что рисовать. Через переменную DISPLAY. Посмотрим:

      ls -l /tmp/.X11-unix/X0
    
      srwxrwxrwx 1 root root 0 апр.  28 07:22 /tmp/.X11-unix/X0
    

    Сокет не имеет размера, ему нужно просто соединять программы между собой (точка-точка). Он позволяет к одному серверу, открывшему сокет, присоединить множество клиентов. Посмотрим открытые сокеты и установленные соединения (программа netstat покажет все)

      netstat
    
      unix  3      [ ]         STREAM     CONNECTED     28596    @/tmp/dbus-RV03IwKbQr
      unix  2      [ ]         DGRAM                    12002
      unix  3      [ ]         STREAM     CONNECTED     77566
      unix  3      [ ]         STREAM     CONNECTED     28143
      unix  3      [ ]         STREAM     CONNECTED     28820    @/tmp/.X11-unix/X0
    

    Видно dbus - это шина, которую придумали, чтобы запущенные программы могли сообщать друг другу о произошедших событиях - чтобы графическая оболочка могла узнать, что произошло подключение флешки, к примеру и нужно ее показать.

  • symbolic link (символическая ссылка) - нужна, чтобы сослаться на файл, не используя жесткую ссылку. Для чего это нужно? Если нет прав - создать ссылку все равно можно, и можно создавать ссылки на файлы на другой ФС. И еще на каталоги нельзя ссылаться с помощью жесткой ссылки.

      sudo find /etc/ -type l
    

    Например системные службы, чтобы запускаться, требуют наличия символических ссылок в определенном каталоге уровня исполнения (/etc/rc1.d). (28:00) Ссылки, начинающиеся со буквы "S" (Start), запускают службу, а "K" (Kill) - останавливают. Например, /etc/rc1.d/S90single - запускает приглашение командной строки. Посмотрим, в каком уровне исполнения мы находимся:

      runlevel
      # N 2
    

    По классике, для запуска графической оболочки используется уровень исполнения 5, но в Ubuntu - 2. Это означает, что в каталоге /etc/rc2.d/ присутствует ссылка, запускающая gdm (все это верно для систем без systemd):

      ls -l /etc/rc2.d/*gdm
      ls -l /etc/rc2.d/S99rc.local
    

    И на самом деле, /etc/rc2.d/S99rc.local ссылается на файл /etc/init.d/rc.local (символическая ссылка). Cистемные администраторы привыкли, что скрипт rc.local лежит прямо в каталоге etc:

      ls -l /etc/rc.local
    

    И это два разных файла. Файл /etc/init.d/rc.local запускает /etc/rc.local - cценарий-обертка.

    Еще пример. Часто в каталоге /dev фигурируют символические ссылки:

      sudo find /dev/ -type l -ls
    

    Там могут быть /dev/cdrom, /dev/dvd и прочие (давно уже в Ubuntu их нет, мода ушла). Можно увидеть cсылку /dev/fd, которая ссылается на /proc/self/fd, из которой процесс может узнать собственные открытые файловые дескрипторы. И еще можно увидеть:

      ls -l /dev/std*
    
      # lrwxrwxrwx 1 root root 15 мая   15 22:35 /dev/stderr -> /proc/self/fd/2
      # lrwxrwxrwx 1 root root 15 мая   15 22:35 /dev/stdin -> /proc/self/fd/0
      # lrwxrwxrwx 1 root root 15 мая   15 22:35 /dev/stdout -> /proc/self/fd/1
    

    По соглашению, стандартный ввод это 0, выход - 1, а ошибки - 2.

  • обычный файл

  • block device (блок-ориентированный специальный файл). Бывают блоковые (блок-ориентированные, блочные) файлы и символьные. Они начинаются с буквы b и c соответственно:

      ls -l /dev/sda
    
      # brw-rw---- 1 root disk 8, 0 мая   15 22:35 /dev/sda
    

    Это жесткий диск, начинается с буквы b. А терминал с буквы c:

      ls -l /dev/tty
    
      # crw-rw-rw- 1 root tty 5, 0 мая   17 11:08 /dev/tty
    

    Разница между ними в том, что операция записи в символьное устройство... (33:23)

  • directory (каталог, папка)

  • char device

  • FIFO/pipe

⚠️ **GitHub.com Fallback** ⚠️