Что такое файловые дескрипторы, объясняемые простыми словами? - PullRequest
319 голосов
/ 10 марта 2011
  1. Что может быть более упрощенным описанием файловых дескрипторов по сравнению с Википедией? Зачем они нужны? Скажем, возьмем процессы оболочки в качестве примера и как они применимы к нему?

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

Ответы [ 11 ]

488 голосов
/ 10 марта 2011

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

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

98 голосов
/ 10 марта 2011

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

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

89 голосов
/ 19 июля 2013

Услышь это изо рта лошади: APUE (Ричард Стивенс).
В ядре все открытые файлы упоминаются дескрипторами файлов. Файловый дескриптор является неотрицательным числом.

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

Two Process

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

16 голосов
/ 24 марта 2017

Больше очков относительно 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. FD для конкретного процесса можетможно увидеть в /proc/$pid/fd (в системах на основе Unix).

14 голосов
/ 24 октября 2016

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

12 голосов
/ 22 сентября 2018

Другие ответы добавили отличные вещи. Я добавлю только мои 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 easy с помощью lsof -p PID, или мы можем увидеть то же самое, если мы ls /proc/PID/fd.

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

fd table

Вы можете спросить себя, где эти файловые дескрипторы физически и что хранится в /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) и
  • Символические ссылки
4 голосов
/ 02 сентября 2018

Файловые дескрипторы (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»
Таким образом, вывод программы не загроможден ошибками.

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

3 голосов
/ 21 декабря 2016

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

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

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

Первый файл, используемый в процессе, - file0 второй file1 , третий file2 и т. д.

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

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

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

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

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

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

2 голосов
/ 03 октября 2018

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

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

Помимо всех упрощенных ответов.
Если вы работаете с файлами в 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
...