Чим відрізняється дескриптор файлу від вказівника на файл?


Відповіді:


144

Дескриптор файлу - це ціле число "ручка" низького рівня, яке використовується для ідентифікації відкритого файлу (або сокета або будь-якого іншого) на рівні ядра в Linux та інших системах, схожих на Unix.

Проходьте «голі» дескриптори файлів реальних викликів Unix, наприклад read(), write()і так далі.

FILEПокажчик являє собою стандартну бібліотеку рівня конструкт C, використовуваний для подання файла. FILEОбгортання дескриптор файлу, і додає буферизацию і інші функції , щоб зробити / O простіше я.

Ви передаєте FILEпокажчики на стандартні функції C, такі як fread()і fwrite().


@nvl: fildes, безумовно, доступна для Windows, наприклад, msdn.microsoft.com/en-us/library/z0kc8e3z%28VS.80%29.aspx
kennytm

2
@unwind Що ви мали на увазі під "голими" дескрипторами файлів? Пов'язане посилання говорить, що fdце перший аргумент read(). Чому ви називаєте це оголеним?
Geek

3
@Geek У порівнянні зі стандартним FILE *типом бібліотеки , дескриптор цілочисельних файлів "менш завершений", тобто "голий".
розмотує

57

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

Ви можете отримати дескриптор файлу з FILE *використанням, fileno()а ви можете відкрити буферизацію FILE *з дескриптора файлів за допомогоюfdopen()


12
+1 для вказівки fileno (), організація довідкових сторінок робить цю проблему важкою. Те саме для fdopen ().
BD у Rivenhill

20

Дескриптор файлу - це лише ціле число, яке ви отримуєте від open()дзвінка POSIX . Використовуючи стандартний C, fopen()ви отримуєте FILEструктуру назад. FILEСтруктура містить цей дескриптор файлу серед інших речей , таких як кінець з файлу і індикатора помилки, положення потоку і т.д.

Тож використання fopen()дає певну кількість абстракцій порівняно з open(). Як правило, ви повинні використовувати, fopen()оскільки це більш портативно, і ви можете використовувати всі інші стандартні функції C, які використовують FILEструктуру, тобто fprintf()сім'ю.

Немає проблем із продуктивністю, що використовує будь-яку.


8
+1 для підвищення портативності. FILE є частиною бібліотеки Standard C (назад до C89 / C90); Дескриптори файлів не є.
tomlogic

15

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

Дескриптор файлу:

Дескриптор файлу - ціле значення, повернене open()системним викликом.

int fd = open (filePath, mode);

  1. Обробник низького / ядра.
  2. Прочитати () та записати () системні дзвінки UNIX.
  3. Не включає буферизацію та подібні функції.
  4. Менш портативний і не має ефективності.

Покажчик файлу:

Файл Покажчик являє собою покажчик на структуру C , повернутої fopen()бібліотечної функцією, яка використовується для ідентифікації файлу, обгорткового дескриптор файлу, буферної функціональність і все інших функціональних можливостей, необхідних для введення / виведення операція .The покажчик файлу має типу FILE , визначення якого можна знайти в "/usr/include/stdio.h" . Це визначення може відрізнятися від одного компілятора до іншого.

FILE *fp = fopen (filePath, mode);

// A FILE Structure returned by fopen 
    typedef struct 
    {
        unsigned char   *_ptr;
        int     _cnt;
        unsigned char   *_base;
        unsigned char   *_bufendp;
        short   _flag;
        short   _file;
        int     __stdioid;
        char    *__newbase;
#ifdef _THREAD_SAFE
        void *_lock;
#else
        long    _unused[1];
#endif
#ifdef __64BIT__
        long    _unused1[4];
#endif /* __64BIT__ */
    } FILE;
  1. Це інтерфейс високого рівня.
  2. Передано для функцій fread () та fwrite ().
  3. Включає буферизацію, індикацію помилок та виявлення EOF тощо.
  4. Забезпечує більш високу портативність та ефективність.

1
Чи можете ви створити резервну копію заявки на підвищення ефективності? Я ніколи цього не чув.
Гід

1
Заява про ефективність може бути наслідком буферизації. За допомогою дескриптора файлів кожне читання () або запис () є систематичним викликом, і кожен syscall слід вважати дорогим. З FILE * буферизація означає, що деякі зчитування та записування не будуть сискликами.
Майк Спір

12

Хочете додати бали, які можуть бути корисними.

ПРО FILE *

  1. не можна використовувати для міжпроцесорного зв'язку (IPC).
  2. використовуйте його тоді, коли вам потрібно вбудований вхід / вивід загального призначення (printf, frpintf, snprintf, scanf)
  3. Я використовую його багато разів для налагодження журналів. наприклад,

                 FILE *fp;
                 fp = fopen("debug.txt","a");
                 fprintf(fp,"I have reached till this point");
                 fclose(fp);

ПРО FILE DESCRIPTOR

  1. Зазвичай використовується для IPC.

  2. Дає низькорівневий контроль файлам у * nix системах (пристроях, файлах, сокетах тощо), отже, більш потужним, ніж на FILE *.


Ви не можете використовувати fdopen()такі речі, як IPC та пристрої FILE*?
освейн

Власне, і так, і ні. Ви не можете налаштувати та ініціалізувати IPC за допомогою FILE*, але ви можете створити FILE*з дескриптора файлу (fdopen() ), а пізніше закриття символу FILEтакож закриє дескриптор. Тому ви можете робити IPC, але вам доведеться трохи попрацювати з дескрипторами файлів, щоб полегшити будь-який прямий IPC.
Micah W

3

FILE *є більш корисним при роботі з текстовими файлами і призначеним для користувача уведенням / висновком, оскільки він дозволяє використовувати функції API , як sprintf(), sscanf(), fgets(), і feof()т.д.

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


1
+1, тому що ви додали файли, зіставлені з пам’яттю, оскільки на мій момент читання інші відповіді вже надані.
ernie.cordell

3

Просто записка, щоб закінчити дискусію (якщо зацікавлено) ....

fopenможе бути незахищеним, і ви, ймовірно, повинні використовувати fopen_sабо openвстановити ексклюзивні біти. C1X пропонує xрежими, тож ви можете fopenз режимами "rx","wx" і т.д.

Якщо ви використовуєте open, ви можете розглянутиopen(..., O_EXCL | O_RDONLY,... ) або open(..., O_CREAT | O_EXCL | O_WRONLY,... ).

Дивіться, наприклад, Не робіть припущення щодо fopen () та створення файлів .


Як fopen_sце здається недоступним POSIX, я припускаю, що найпотужніша думка була б до того open(2)часу fdopen(2). (залишаючи вікна вбік). Крім того, що було б швидше fopen_s()чи open(2)за яким слід fdopen(2)?
Mihir

1

Системні виклики здебільшого використовують дескриптор файлів, наприклад, readта write. Функція бібліотеки використовуватиме покажчики файлів ( printf, scanf). Але функції бібліотеки використовують лише внутрішньо системні дзвінки.


Я не впевнений, чому ви говорите, що функції бібліотеки використовують лише внутрішні системні виклики: Якщо ви маєте на увазі стандартні функції CI / O (або будь-які інші з цього приводу) функції, я не впевнений, що це (універсально?) Правда. Інакше це не те, що ви сказали, тож я хотів би, щоб мова у вашій посаді трохи очистилася. Останнє речення мене бентежить.
ernie.cordell

1

Я знайшов хороший ресурс тут , що дає докладний огляд відмінностей між ними:

Коли ви хочете зробити введення чи виведення у файл, у вас є вибір двох основних механізмів представлення зв'язку між вашою програмою та файлом: дескриптори файлів та потоки. Дескриптори файлів представлені у вигляді об'єктів типу int, а потоки представлені у вигляді FILE * об'єктів.

Дескриптори файлів забезпечують примітивний низькорівневий інтерфейс для операцій введення та виводу. І дескриптори файлів, і потоки можуть представляти з'єднання з пристроєм (наприклад, терміналом) або трубою або сокетом для зв'язку з іншим процесом, а також звичайним файлом. Але, якщо ви хочете виконувати керуючі операції, характерні для певного виду пристроїв, ви повинні використовувати дескриптор файлу; не існує засобів, щоб використовувати потоки таким чином. Ви також повинні використовувати дескриптори файлів, якщо вашій програмі потрібно робити введення або виведення в спеціальних режимах, таких як неблокуючий (або опитуваний) вхід (див. Прапори статусу файлу).

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

Основна перевага використання інтерфейсу потоку полягає в тому, що набір функцій для виконання фактичних операцій вводу і виводу (на відміну від операцій управління) на потоках набагато багатший і потужніший, ніж відповідні засоби для дескрипторів файлів. Інтерфейс дескриптора файлів забезпечує лише прості функції для передачі блоків символів, але інтерфейс потоку також забезпечує потужні відформатовані функції введення та виведення (printf і scanf), а також функції введення та виведення, орієнтованих на символи та лінії.

Оскільки потоки реалізовані з точки зору дескрипторів файлів, ви можете витягнути дескриптор файлу з потоку і виконувати операції низького рівня безпосередньо на дескрипторі файлу. Ви також можете спочатку відкрити з'єднання як дескриптор файлу, а потім зробити потік, пов’язаний з цим дескриптором файлу.

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

Якщо вас турбує переносимість ваших програм до інших систем, крім GNU, ви також повинні знати, що дескриптори файлів не такі портативні, як потоки. Ви можете сподіватися, що будь-яка система, що працює під керуванням ISO C, підтримує потоки, але системи, що не належать до GNU, можуть взагалі не підтримувати дескриптори файлів або можуть реалізовувати лише підмножину функцій GNU, які працюють на дескрипторах файлів. Більшість функцій дескриптора файлів у бібліотеці GNU C включені до стандарту POSIX.1.

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