Що таке дескриптори файлів, пояснені простими словами?


383
  1. Що було б більш спрощеним описом дескрипторів файлів у порівнянні з Вікіпедією? Чому вони потрібні? Скажімо, візьміть приклади оболонок як приклад і як це застосовується для цього?

  2. Чи містить таблиця процесів більше одного дескриптора файлів. Якщо так, то чому?


3
Що з поняттями stdin stdout stderr тощо? У мене є такий екземпляр, як скажімо, процес браузера, і він відкрив деякі тимчасові файли для відображення мого html. Процес використовує той самий fd для читання / запису? Також таблиця процесів ....... вона містить такі записи, як fd0 покажчик fd1 покажчик fd2 покажчик ..... це означає, що всі ці файли знаходяться в оперативній пам'яті? Чому ще вказівники?
Нішант

43
Коли ви відкриваєте файл, ОС створює потік до цього файлу і підключає цей потік до відкритого файлу, дескриптор насправді представляє цей потік. Так само є деякі потоки за замовчуванням, створені ОС. Ці потоки підключені до вашого терміналу замість файлів. Отже, коли ви щось пишете в терміналі, воно переходить до потоку stdin та ОС. І коли ви пишете команду "ls" на термінал, ОС записує вихід у stdout stream. Потік stdout підключений до терміналу монітора, щоб ви могли бачити вихід там.
Таяб

1
Що стосується прикладу веб-переглядача, то не обов’язково, щоб браузер зберігав файли відкритими. Це залежить від реалізації браузера, але в більшості випадків браузер відкриває тимчасовий файл, записує файл і закриває файл, тому не потрібно, щоб файл відкривався, навіть якщо веб-сторінка відкрита. І дескриптор просто містить інформацію про файл і не обов'язково зберігати файл в оперативній пам'яті. Коли ви читаєте дані з дескриптора, ОС читає дані з жорсткого диска. Інформація в дескрипторі файлів просто відображає розташування файлу на жорсткому диску тощо.
Tayyab

5
Дескриптор файлу до файлу - це не один до одного зіставлення. Я міг би відкрити один і той же файл 4 рази і отримати 4 різних дескриптора файлів. Кожен з яких міг би бути використаний (залежно від прапорців, що передаються відкритим ()) для читання, написання чи обох. Що стосується того, чи файл живе в оперативній пам’яті чи на диску - це приховане від вас ядро ​​та різні його кеші. Зрештою, те, що є кешем, відповідатиме тому, що є на диску (для запису), а ядро ​​не повернеться до диска, для читання, якщо дані вже є в кеші.
Beano

7
Це гарна стаття, щоб зрозуміти її легко bottomupcs.com/file_descriptors.xhtml
Кришан Гопал,

Відповіді:


561

Простими словами, коли ви відкриваєте файл, операційна система створює запис, який представляє цей файл і зберігає інформацію про цей відкритий файл. Отже, якщо у вашій ОС відкрито 100 файлів, то в ОС буде 100 записів (десь у ядрі). Ці записи представлені цілими числами на зразок (... 100, 101, 102 ....). Цей вхідний номер - дескриптор файлу. Отже, це лише ціле число, яке однозначно представляє відкритий файл в операційній системі. Якщо ваш процес відкриє 10 файлів, то у таблиці Process буде 10 записів для дескрипторів файлів.

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


7
Крім того, саме тому у вас може не вистачати дескрипторів файлів, якщо ви відкриєте безліч файлів одночасно. Що не дозволить * nix системам працювати, оскільки вони відкривають дескриптори для наповнення /procпостійно.
Спенсер Ратбун

8
@ErbenMo: Ні, це може бути не однаково. Коли ви відкриєте файл, операційна система призначить доступний FD, а коли ви закриєте його, ОС звільнить FD і може призначити цей FD іншому файлу, відкритому після цього. Шлях його операційної системи відстежувати відкриті файли, і це не має нічого спільного з конкретним файлом.
Тайяб

49
" Отже, це лише ціле число, яке однозначно представляє відкритий файл в операційній системі. " Це неправильно. Це ціле число унікально представляє відкритий файл у процесі . Дескриптор файлу 0, наприклад, представлятиме один відкритий файл в одному процесі та зовсім інший відкритий файл в іншому.
Кіт Томпсон

15
@Tayyab: Я вважаю, ти помилився. Дескриптори файлів 0, 1 і 2 - це стандартний вхід, стандартний вихід і стандартна помилка для кожного запущеного процесу. Успішний початковий виклик open()дасть вам дескриптор файлу 3, навіть якщо інший запущений процес має дескриптор файлу 3. Див . Визначення POSIXopen() : "Функція open () повертає дескриптор файлу для названого файлу, який є найнижчим. Дескриптор файлу наразі не відкритий для цього процесу . " (наголос додано).
Кіт Томпсон

17
@KeithThompson: Так, ти маєш рацію. Насправді це стосується рівня абстракції. Насправді ведуться дві таблиці, де перша - це один процес, а друга - загальносистемна. FD в таблиці за процесом (тобто fdtable) не є унікальною системою. Однак він відображає таблицю v-node, яка містить унікальні записи для всієї системи. Отже, коли ви викликаєте функцію fopen () і fileno () для перевірки дескриптора, ви можете отримати одне і те ж число FD у двох різних процесах, оскільки він повертає індекс fdtable, який є на процес. Дякуємо, що ви виховали його !!
Таяб

116

Дескриптор файлу - це непрозора ручка, яка використовується в інтерфейсі між простором користувача та ядра для ідентифікації файлових / сокетних ресурсів. Тому при використанні open()або socket()(системні виклики для інтерфейсу до ядра) вам надається дескриптор файлу, який є цілим числом (це фактично індекс у структурі процесів u, але це не важливо). Тому, якщо ви хочете , щоб безпосередньо взаємодіяти з ядром, використовуючи системні виклики read(), write(), і close()т.д. ручка ви використовуєте файловий дескриптор.

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


6
Я особисто вважаю, що ця відповідь краща за ту, що зазначена як відповідь. Отримано.
Тарік

101

Почуйте це з конячого рота: APUE (Річард Стівенс).
До ядра всі відкриті файли посилаються Дескриптори файлів. Дескриптор файлу - це негативне число.

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

Два процеси

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


1
Оскільки 0, 1, 2 пов'язані зі "stdin", "stdout" та "stderr" процесу, чи можемо ми використовувати ці дескриптори одночасно для різних процесів?
Тарік

@Tarik: дескриптори файлів є для кожного процесу. Щоб побачити це, завантажте osquery та виконайте osqueryi <<< echo '.all process_open_files'в bash shell.
Бен Крізі

29

Інші відповіді додали чудові речі. Я додам лише свої 2 копійки.

Згідно з Вікіпедією, ми точно знаємо: дескриптор файлу - це невід'ємне ціле число. Найголовніше, що мені здається, відсутнє, було б сказати:

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

Ми знаємо, що найвідоміші дескриптори файлів: 0, 1 і 2. 0 відповідає STDIN1 STDOUT, 2 і 2 STDERR.

Скажімо, візьміть приклади оболонок як приклад і як це застосовується для цього?

Перевірте цей код

#>sleep 1000 &
[12] 14726

Ми створили процес з id 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

4-й стовпчик 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 вказує тип файлу. Деякі з значень TYPE:

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

Але всі дескриптори файлів - це CHR - спеціальний файл символів (або файл пристрою символів)

Тепер ми можемо визначити Дескриптори файлів для STDIN, STDOUTі STDERRлегко lsof -p PID, або ми можемо побачити те саме, якщо ми ls /proc/PID/fd.

Зауважте також, що таблиця дескрипторів файлів, за якою відслідковується ядро, не збігається з таблицею файлів або таблицею вкладень. Це окремо, як пояснили деякі інші відповіді.

fd таблиця

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

1
Дякую. Дійсно, важливо зазначити, що це відбувається за кожним процесом! Це допомагає візуалізувати речі краще.
Нішант

1
Типи файлів, визначені ОС, про які ви згадали у своїй відповіді, справді допомагають зрозуміти файли на нижчому рівні.
Рохан Бхале

20

Більше пунктів щодо 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).


16

Як додаток до інших відповідей, unix розглядає все як файлову систему. Ваша клавіатура - це файл, який читається лише з точки зору ядра. Екран - це файл лише для запису. Аналогічно, папки, пристрої введення-виведення тощо вважаються також файлами. Щоразу, коли файл відкривається, скажіть, коли драйвери пристрою [для файлів пристрою] вимагають відкрити (), або процес відкриває файл користувача, ядро ​​виділяє дескриптор файлу, ціле число, яке визначає доступ до цього файлу, таким чином, воно лише читається , пишіть лише тощо. [для довідки: https://en.wikipedia.org/wiki/Everything_is_a_file ]


Дескриптори файлів також можуть посилатися на речі, які не існують у файловій системі, як-от анонімні труби та мережеві розетки.
kbolino

12

Дескриптори файлів (FD):

  • У Linux / Unix все є файлом. Звичайний файл, каталоги та навіть пристрої - це файли. Кожен файл має пов'язаний номер, який називається File Descriptor (FD).
  • На екрані також є Дескриптор файлів. Коли програма виконується, висновок надсилається у File Descriptor екрану, і ви бачите вихід програми на моніторі. Якщо вивід буде надісланий Файловому дескриптору принтера, програмний вихід був би надрукований.

    Перенаправлення помилок:
    кожного разу, коли ви виконуєте програму / команду на терміналі, завжди відкриваються 3 файли
    1. стандартний вхід
    2. стандартний вихід
    3. стандартна помилка.

    Ці файли завжди є при кожному запуску програми. Як пояснювалося раніше, дескриптор файлу пов'язаний з кожним із цих файлів. Дескриптор
    файлу                                        файлів
    Стандартний вхід STDIN 0
    Стандартний вихід STDOUT 1
    Стандартна помилка STDERR 2

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

$ ls mydir 2> файли помилок.txt

Дескриптор файлу для стандартної помилки - 2.
Якщо немає жодного каталогу, названого mydir, результат виведення команди буде збережений у файл errorfile.txt
За допомогою "2>" ми перенаправляємо вихід помилки у файл з назвою "filefile error. txt "
Таким чином, вихід програми не захаращений помилками.

Я сподіваюся, що ви отримали свою відповідь.


5

Будь-яка операційна система має процеси (p's), наприклад p1, p2, p3 тощо. Кожен процес зазвичай забезпечує постійне використання файлів.

Кожен процес складається з дерева процесів (або таблиці процесів, в іншому формулюванні).

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

Перший файл , який використовується в способі є file0 , друга файл1 , третій файл2 , і так далі.

Будь-яке таке число є дескриптором файлів.

Дескриптори файлів зазвичай є цілими числами (0, 1, 2, а не 0,5, 1,5, 2,5).

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

Аналогічно, коли ви відкриваєте мережевий сокет, він має дескриптор сокета.

У деяких операційних системах вичерпані дескриптори файлів, але такий випадок вкрай рідкісний, і пересічний користувач комп'ютера не повинен з цього переживати.

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


Детальніше про FD в Linux можна прочитати

1
чудова відповідь :)
humble_wolf

5

Дескриптори файлів

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

1

Доповнення до всіх спрощених відповідей.
Якщо ви працюєте з файлами в bash script, краще використовувати дескриптор файлів.
Наприклад: -
Ви хочете читати та писати з / у файл "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

-5

Дескриптори файлів - це дескриптори файлу. Вони дають посилання на файл. За допомогою них ми можемо читати, писати та відкривати файл.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.