В чем разница между файловым дескриптором и файловым указателем?


Ответы:


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 в Ривенхилле,

20

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

Таким образом, использование fopen()дает вам определенную абстракцию по сравнению с open(). В общем, вам следует использовать, fopen()поскольку это более переносимо, и вы можете использовать все другие стандартные функции C, которые используют FILEструктуру, т. Е.fprintf() И семейство.

Нет никаких проблем с производительностью при использовании.


8
+1 за повышение мобильности. ФАЙЛ является частью стандартной библиотеки C (начиная с C89 / C90); файловых дескрипторов нет.
tomlogic

15

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

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

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

int fd = open (filePath, mode);

  1. Обработчик низкого уровня / уровня ядра.
  2. Pass для чтения () и записи () системных вызовов UNIX.
  3. Не включает буферизацию и подобные функции.
  4. Менее портативный и неэффективный.

Указатель файла:

Указатель файла - это указатель на структуру C, возвращаемую fopen()библиотечной функцией, которая используется для идентификации файла, упаковки дескриптора файла, функций буферизации и всех других функций, необходимых для операции ввода-вывода . Указатель файла имеет тип 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
Заявление об «эффективности» могло быть связано с буферизацией. При использовании файлового дескриптора каждый read () или write () является системным вызовом, и каждый системный вызов следует рассматривать как дорогостоящий. В случае 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*?
Osvein

Собственно и да, и нет. Вы не можете настроить и инициализировать 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, я предполагаю, что наиболее переносимым вариантом будет to open(2)and then 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.