Что такое файловые дескрипторы, объясняемые простыми словами?

  1. Что может быть более упрощенным описанием файловых дескрипторов по сравнению с Википедией? Зачем они нужны? Скажем, возьмем процессы оболочки в качестве примера и как это применимо к нему?

  2. Содержит ли таблица процессов более одного дескриптора файла. Если да, то почему?

14 ответов

Решение

Проще говоря, когда вы открываете файл, операционная система создает запись для представления этого файла и сохраняет информацию об этом открытом файле. Так что если в вашей ОС открыто 100 файлов, то в ОС будет 100 записей (где-то в ядре). Эти записи представлены целыми числами, такими как (... 100, 101, 102....). Этот номер записи является дескриптором файла. Так что это просто целое число, которое уникально представляет открытый файл в операционной системе. Если ваш процесс открывает 10 файлов, то ваша таблица процессов будет иметь 10 записей для файловых дескрипторов.

Аналогично, когда вы открываете сетевой сокет, он также представляется целым числом и называется дескриптором сокета. Я надеюсь, вы понимаете.

Файловый дескриптор - это непрозрачный дескриптор, который используется в интерфейсе между пользователем и пространством ядра для идентификации ресурсов файла / сокета. Поэтому, когда вы используете open() или же socket() (системные вызовы для взаимодействия с ядром), вам предоставляется дескриптор файла, который является целым числом (на самом деле это индекс в структуре процессов, но это не важно). Поэтому, если вы хотите напрямую взаимодействовать с ядром, используйте системные вызовы для read(), write(), close() и т.д. дескриптор, который вы используете, является дескриптором файла.

На системные вызовы накладывается слой абстракции, который является stdio интерфейс. Это обеспечивает больше функциональности / возможностей, чем базовые системные вызовы. Для этого интерфейса вы получите непрозрачную ручку FILE*, который возвращается fopen() вызов. Есть много много функций, которые используют stdio интерфейс fprintf(), fscanf(), fclose(), которые существуют, чтобы сделать вашу жизнь проще. В С, stdin, stdout, а также stderr являются FILE*, которые в UNIX соответственно отображаются на файловые дескрипторы 0, 1 а также 2,

Услышь это изо рта лошади: APUE (Ричард Стивенс).
В ядре все открытые файлы упоминаются дескрипторами файлов. Файловый дескриптор является неотрицательным числом.
Когда мы открываем существующий файл или создаем новый файл, ядро ​​возвращает файловый дескриптор процессу. Ядро поддерживает таблицу всех открытых дескрипторов файлов, которые используются. Выделение файловых дескрипторов, как правило, является последовательным, и они выделяются для файла в качестве следующего свободного файлового дескриптора из пула бесплатных файловых дескрипторов. Когда мы закрываем файл, дескриптор файла освобождается и становится доступным для дальнейшего выделения.
Смотрите это изображение для более подробной информации:
Два процесса

Когда мы хотим прочитать или записать файл, мы отождествляем файл с дескриптором файла, который был возвращен вызовом функции open() или create(), и используем его в качестве аргумента для read() или write ().
По соглашению системные оболочки UNIX связывают дескриптор файла 0 со стандартным вводом процесса, дескриптор файла 1 со стандартным выводом и дескриптор файла 2 со стандартной ошибкой.
Дескриптор файла варьируется от 0 до OPEN_MAX.
Для получения дополнительной информации, прочитайте 3-ю главу книги APUE.

Другие ответы добавили отличные вещи. Я добавлю только мои 2 цента.

Согласно Википедии мы точно знаем: дескриптор файла является неотрицательным целым числом. Самая важная вещь, которую я считаю отсутствующей, это сказать:

Файловые дескрипторы привязаны к идентификатору процесса.

Мы знаем, что самые известные файловые дескрипторы 0, 1 и 2. 0 соответствует STDIN1 к STDOUTи 2 к STDERR,

Скажем, возьмем процессы оболочки в качестве примера и как это применимо к нему?

Проверьте этот код

#>sleep 1000 &
[12] 14726

Мы создали процесс с идентификатором 14726 (PID). С использованием lsof -p 14726 мы можем получить такие вещи:

COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF    NODE NAME
sleep   14726 root  cwd    DIR    8,1     4096 1201140 /home/x
sleep   14726 root  rtd    DIR    8,1     4096       2 /
sleep   14726 root  txt    REG    8,1    35000  786587 /bin/sleep
sleep   14726 root  mem    REG    8,1 11864720 1186503 /usr/lib/locale/locale-archive
sleep   14726 root  mem    REG    8,1  2030544  137184 /lib/x86_64-linux-gnu/libc-2.27.so
sleep   14726 root  mem    REG    8,1   170960  137156 /lib/x86_64-linux-gnu/ld-2.27.so
sleep   14726 root    0u   CHR  136,6      0t0       9 /dev/pts/6
sleep   14726 root    1u   CHR  136,6      0t0       9 /dev/pts/6
sleep   14726 root    2u   CHR  136,6      0t0       9 /dev/pts/6

Четвертый столбец FD и следующий столбец TYPE соответствуют дескриптору файла и типу дескриптора файла.

Некоторые значения для FD могут быть:

cwd – Current Working Directory
txt – Text file
mem – Memory mapped file
mmap – Memory mapped device

Но настоящий дескриптор файла находится под:

NUMBER – Represent the actual file descriptor. 

Символ после числа, то есть "1u", представляет режим, в котором файл открывается. r для чтения, w для записи, u для чтения и записи.

TYPE указывает тип файла. Некоторые из значений типов:

REG – Regular File
DIR – Directory
FIFO – First In First Out

Но все файловые дескрипторы - это CHR - специальный символьный файл (или файл символьного устройства)

Теперь мы можем определить дескрипторы файлов для STDIN, STDOUT а также STDERR легко с lsof -p PIDили мы можем увидеть то же самое, если мы ls /proc/PID/fd,

Также обратите внимание, что таблица дескрипторов файлов, которую отслеживает ядро, не совпадает с таблицей файлов или таблицей inode. Это отдельные, как объяснили некоторые другие ответы.

таблица ФД

Вы можете спросить себя, где эти файловые дескрипторы физически и что хранится в /dev/pts/6 например

sleep   14726 root    0u   CHR  136,6      0t0       9 /dev/pts/6
sleep   14726 root    1u   CHR  136,6      0t0       9 /dev/pts/6
sleep   14726 root    2u   CHR  136,6      0t0       9 /dev/pts/6

Что ж, /dev/pts/6 живет чисто в памяти. Это не обычные файлы, а так называемые файлы символьных устройств. Вы можете проверить это с помощью: ls -l /dev/pts/6 и они начнут с c, в моем случае crw--w----,

Напомним, что большинство Linux-подобных ОС определяют семь типов файлов:

  • Обычные файлы
  • Справочники
  • Файлы символьных устройств
  • Блокировать файлы устройства
  • Локальные доменные сокеты
  • Именованные трубы (FIFO) и
  • Символические ссылки

Файловые дескрипторы (FD):

  • В Linux/Unix все является файлом. Обычный файл, каталоги и даже устройства являются файлами. Каждый файл имеет связанный номер, называемый дескриптором файла (FD).
  • Ваш экран также имеет дескриптор файла. Когда программа выполняется, вывод передается в дескриптор файла на экране, и вы видите вывод программы на вашем мониторе. Если выходные данные отправляются в дескриптор файла принтера, выходные данные программы будут напечатаны.

    Перенаправление ошибок:
    Всякий раз, когда вы выполняете программу / команду в терминале, всегда открыты 3 файла.
    1. стандартный ввод
    2. стандартный вывод
    3. стандартная ошибка.

    Эти файлы всегда присутствуют при запуске программы. Как объяснено ранее файловый дескриптор, связан с каждым из этих файлов.
    Файловый дескриптор файла
    Стандартный вход STDIN              0
    Стандартный выход STDOUT       1
    Стандартная ошибка STDERR          2

  • Например, при поиске файлов обычно получаются ошибки, в которых отказано в разрешении, или какие-то другие ошибки. Эти ошибки могут быть сохранены в конкретном файле.
    Пример 1

$ ls mydir 2> errorsfile.txt

Дескриптор файла для стандартной ошибки - 2.
Если нет каталога с именем mydir, вывод команды будет сохранен в файле errorfile.txt.
Используя "2>", мы перенаправляем вывод ошибок в файл с именем "errorfile.txt"
Таким образом, вывод программы не загроможден ошибками.

Я надеюсь, что вы получили свой ответ.

Больше очков относительно File Descriptor:

  1. File Descriptors (FD) - неотрицательные целые числа (0, 1, 2, ...) которые связаны с открытыми файлами.

  2. 0, 1, 2 являются стандартными FD, что соответствует STDIN_FILENO, STDOUT_FILENO а также STDERR_FILENO (определено в unistd.h) открывается по умолчанию от имени оболочки при запуске программы.

  3. FD распределяются в последовательном порядке, что означает наименьшее возможное нераспределенное целочисленное значение.

  4. ФД для конкретного процесса можно увидеть в /proc/$pid/fd (в системах на основе Unix).

В дополнение к другим ответам, Unix рассматривает все как файловую систему. Ваша клавиатура - это файл, который доступен только для чтения с точки зрения ядра. Экран - это файл только для записи. Аналогично, папки, устройства ввода-вывода и т. Д. Также считаются файлами. Когда файл открывается, скажем, когда драйверы устройств [для файлов устройств] запрашивают open(), или процесс открывает пользовательский файл, ядро ​​выделяет дескриптор файла, целое число, которое определяет доступ к этому файлу, так что он доступен только для чтения., пишите только и т. д. [для справки: https://en.wikipedia.org/wiki/Everything_is_a_file ]

Файловые дескрипторы

  • В ядре все открытые файлы называются файловыми дескрипторами.
  • Файловый дескриптор является неотрицательным целым числом.
  • Когда мы открываем существующий или создаем новый файл, ядро ​​возвращает файловый дескриптор процессу.
  • Когда мы хотим прочитать или записать файл, мы идентифицируем файл с дескриптором файла, который был перенастроен open или create, в качестве аргумента для чтения или записи.
  • Каждый процесс UNIX имеет 20 файловых дескрипторов, и его удаление имеет номера от 0 до 19, но во многих системах он был расширен до 63.
  • Первые три уже открыты, когда начинается процесс 0: стандартный ввод 1: стандартный вывод 2: стандартный вывод ошибок
  • Когда родительский процесс разветвляется, дочерний процесс наследует файловые дескрипторы родительского процесса.

Все предоставленные ответы великолепны, вот моя версия -

Дескрипторы файлов — это неотрицательные целые числа, которые действуют как абстрактный дескриптор «файлов» или ресурсов ввода-вывода (таких как каналы, сокеты или потоки данных). Эти дескрипторы помогают нам взаимодействовать с этими ресурсами ввода-вывода и делают работу с ними очень простой. Система ввода-вывода видна пользовательскому процессу как поток байтов (поток ввода-вывода). Процесс Unix использует дескрипторы (небольшие целые числа без знака) для ссылки на потоки ввода-вывода. Системные вызовы, связанные с операциями ввода-вывода, принимают дескриптор в качестве аргумента.

Допустимый дескриптор файла находится в диапазоне от 0 до максимального числа дескрипторов, которое можно настроить (ulimit, /proc/sys/fs/file-max). Ядро назначает desc. для стандартного ввода (0), стандартного вывода (1) и стандартной ошибки (2) таблицы FD. Если файл не открывается, fd возвращает -1.

Когда процесс делает успешный запрос на открытие файла, ядро ​​возвращает файловый дескриптор, который указывает на запись в глобальной файловой таблице ядра. Запись таблицы файлов содержит такую ​​информацию, как индекс файла, смещение в байтах и ​​ограничения доступа для этого потока данных (только для чтения, только для записи и т. д.).

Дескрипторы файлов - это не что иное, как ссылки на любой открытый ресурс. Как только вы открываете ресурс, ядро ​​предполагает, что вы будете выполнять над ним какие-то операции. Все коммуникации через вашу программу и ресурс происходят через интерфейс, и этот интерфейс предоставляется файловым дескриптором.

Поскольку процесс может открывать более одного ресурса, ресурс может иметь более одного дескриптора файла.
Вы можете просмотреть все файловые дескрипторы, связанные с процессом, просто запустив,ls -li /proc/<pid>/fd/ здесь pid - это идентификатор вашего процесса

В любой операционной системе запущены процессы (p), скажем, p1, p2, p3 и так далее. Каждый процесс обычно постоянно использует файлы.

Каждый процесс состоит из дерева процессов (или таблицы процессов, в другой фразе).

Обычно операционные системы представляют каждый файл в каждом процессе числом (то есть в каждом дереве / таблице процессов).

Первый файл, используемый в процессе, это файл0, второй - файл1, третий - файл2 и так далее.

Любое такое число является дескриптором файла.

Файловые дескрипторы обычно являются целыми числами (0, 1, 2, а не 0,5, 1,5, 2,5).

Поскольку мы часто описываем процессы как "таблицы процессов", и учитывая, что в таблицах есть строки (записи), мы можем сказать, что ячейка дескриптора файла в каждой записи использует для представления всей записи.

Аналогичным образом, когда вы открываете сетевой сокет, он имеет дескриптор сокета.

В некоторых операционных системах вы можете исчерпать файловые дескрипторы, но такой случай крайне редок, и обычному пользователю компьютера не стоит беспокоиться об этом.

Файловые дескрипторы могут быть глобальными (процесс A начинается, скажем, с 0, а заканчивается, скажем, с 1; процесс B начинается с, скажем, 2, а заканчивается, скажем, с 3) и т. Д., Но, насколько я знаю, обычно в современных операционных системах файл дескрипторы не являются глобальными и фактически зависят от процесса (процесс A начинается, скажем, с 0 и заканчивается, скажем, с 5, а процесс B начинается с 0 и заканчивается, например, с 10).

Дополнение к прежде всего упрощенным ответам.
Если вы работаете с файлами в сценарии bash, лучше использовать файловый дескриптор.
Например:-
Вы хотите читать и писать из / в файл "test.txt".
Используйте дескриптор файла, как показано ниже

FILE=$1 # give the name of file in the command line
exec 5<>$FILE # '5' here act as the file descriptor
# Reading from the file line by line using file descriptor
while read LINE; do
    echo "$LINE"
done <&5

# Writing to the file using descriptor
echo "Adding the date: `date`" >&5 
exec 5<&- # Closing a file descriptor

Я не знаю код ядра, но я добавлю сюда свои два цента, так как я думал об этом некоторое время, и я думаю, что это будет полезно.

Когда вы открываете файл, ядро ​​возвращает файловый дескриптор для взаимодействия с этим файлом.

Дескриптор файла - это реализация API для открываемого файла. Ядро создает этот файловый дескриптор, сохраняет его в массиве и передает вам.

Для этого API требуется реализация, позволяющая, например, читать и записывать в файл.

Теперь подумайте о том, что я сказал еще раз, вспомнив, что все является файлом - принтеры, мониторы, HTTP-соединения и т. Д.

Это мое резюме после прочтения https://www.bottomupcs.com/file_descriptors.xhtml .

Файловые дескрипторы являются дескрипторами файла. Они дают ссылки на файл. С их помощью мы можем читать, писать и открывать файл.

Другие вопросы по тегам