Вопрос с собеседования · Основы

Что такое файловый дескриптор?

JuniorОперационные системы
Ещё спрашивают так:
  • Что означает ошибка Too many open files?
  • Почему в Unix «всё есть файл»?
  • Что такое stdin, stdout и stderr?
Коротко

Файловый дескриптор — небольшое целое число, по которому процесс обращается к открытому ресурсу: файлу, сокету, каналу, устройству.

  • 0, 1, 2 — stdin, stdout, stderr
  • Лимит на процесс (ulimit -n, часто 1024) — при утечке «Too many open files»
  • Сокеты тоже дескрипторы: каждое соединение тратит один

А ещё Закрывать ресурсы: try-with-resources, with, defer

Подробно

Когда процесс открывает файл (open), ядро создаёт запись об открытом ресурсе и возвращает процессу индекс в его таблице — файловый дескриптор. Дальше все операции идут по номеру: read(fd, ...), write(fd, ...), close(fd).

«Всё есть файл». Через тот же интерфейс в Unix работают сокеты, каналы (| в shell), терминалы, устройства, таймеры (timerfd), события (eventfd). Поэтому одним epoll можно ждать готовности и сетевых соединений, и каналов, а перенаправление > в shell просто подменяет дескриптор 1.

Стандартные: 0 — stdin, 1 — stdout, 2 — stderr. 2>&1 — направить stderr туда же, куда stdout.

Лимиты. На процесс есть ограничение числа открытых дескрипторов — ulimit -n, по умолчанию часто 1024 (мягкий лимит). Для сервера с десятками тысяч соединений его поднимают (LimitNOFILE в systemd, nofile в limits.conf). Есть и общесистемный fs.file-max.

Too many open files (EMFILE) — обычно не «мало лимита», а утечка: файлы, сокеты или HTTP-соединения открываются и не закрываются. Ищут через ls /proc/<pid>/fd | wc -l и lsof -p <pid> — видно, чего накопилось. Лечение — закрывать ресурсы гарантированно: try-with-resources в Java, with в Python, defer в Go; переиспользовать HTTP-клиент с пулом вместо нового клиента на каждый запрос.

Наследование. После fork дочерний процесс получает копии дескрипторов; чтобы не утекали в запускаемые программы, их открывают с флагом O_CLOEXEC. Удалённый, но открытый файл продолжает занимать место на диске, пока дескриптор не закрыт — классическая загадка «диск полон, а файлов нет» с лог-файлом, который удалили у работающего процесса.

Пример

$ ulimit -n
1024
$ ls /proc/$(pgrep -f app.jar)/fd | wc -l
1019
$ lsof -p $(pgrep -f app.jar) | awk '{print $5}' | sort | uniq -c
    12 REG
   987 IPv4      # сокеты не закрываются — утечка соединений

Что хотят услышать

  • Дескриптор — номер открытого ресурса в таблице процесса.
  • Сокеты и каналы — тоже дескрипторы.
  • 0, 1, 2 и перенаправление.
  • Too many open files: лимит, утечки, диагностика через /proc и lsof.

Частые ошибки

  • Просто поднимать лимит, не поискав утечку.
  • Думать, что удалённый файл сразу освобождает место.

Проверьте себя

Один верный вариант. Подумайте, потом откройте ответ.

Показать варианты и ответ
  • ✗Полный путь к файлу на диске, по которому процесс каждый раз заново открывает файл при чтении или записи
  • ✗Номер процесса, открывшего файл, в таблице процессов
  • ✗Сокеты не используют дескрипторы, только файлы на диске
  • ✓Целое число, по которому процесс обращается к открытому ресурсу

Что спросят дальше

Связанные вопросы

Партнёр платформы

Разбор собеседования с sotto

После собеседования sotto разбирает разговор: оценка, каждый вопрос — хорошо, частично или слабо, чего не хватило в ответе и над чем поработать к следующему разу. Первые 30 минут бесплатно.

Разбор собеседования