Что такое файловые дескрипторы, объясняемые простыми словами?
Что может быть более упрощенным описанием файловых дескрипторов по сравнению с Википедией? Зачем они нужны? Скажем, возьмем процессы оболочки в качестве примера и как это применимо к нему?
Содержит ли таблица процессов более одного дескриптора файла. Если да, то почему?
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 соответствует STDIN
1 к 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 файла.- стандартный ввод
- стандартный вывод
- стандартная ошибка.
Эти файлы всегда присутствуют при запуске программы. Как объяснено ранее файловый дескриптор, связан с каждым из этих файлов.
Файловый дескриптор файла
Стандартный вход STDIN 0
Стандартный выход STDOUT 1
Стандартная ошибка STDERR 2 - Например, при поиске файлов обычно получаются ошибки, в которых отказано в разрешении, или какие-то другие ошибки. Эти ошибки могут быть сохранены в конкретном файле.
Пример 1
$ ls mydir 2> errorsfile.txt
Дескриптор файла для стандартной ошибки - 2.
Если нет каталога с именем mydir, вывод команды будет сохранен в файле errorfile.txt.
Используя "2>", мы перенаправляем вывод ошибок в файл с именем "errorfile.txt"
Таким образом, вывод программы не загроможден ошибками.
Я надеюсь, что вы получили свой ответ.
Больше очков относительно File Descriptor
:
File Descriptors
(FD) - неотрицательные целые числа(0, 1, 2, ...)
которые связаны с открытыми файлами.0, 1, 2
являются стандартными FD, что соответствуетSTDIN_FILENO
,STDOUT_FILENO
а такжеSTDERR_FILENO
(определено вunistd.h
) открывается по умолчанию от имени оболочки при запуске программы.FD распределяются в последовательном порядке, что означает наименьшее возможное нераспределенное целочисленное значение.
ФД для конкретного процесса можно увидеть в
/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 .
Файловые дескрипторы являются дескрипторами файла. Они дают ссылки на файл. С их помощью мы можем читать, писать и открывать файл.