Альтернативы использованию stat() для получения типа файла?

Существуют ли какие-либо альтернативы stat (который есть в большинстве систем Unix), которые могут определить тип файла? В справочной странице говорится, что вызов stat стоит дорого, и мне нужно довольно часто вызывать его в своем приложении.


person helpermethod    schedule 01.04.2010    source источник
comment
Что вы имеете в виду под типом файла? Что именно вы хотите определить?   -  person Ayman Hourieh    schedule 01.04.2010
comment
Это для того, чтобы просто определить длину, посмотреть, является ли это символической ссылкой ... что вам на самом деле нужно от stat()?   -  person Tim Post♦    schedule 01.04.2010
comment
@Ayman: вопрос вполне ясен - наверное. В Unix типы файлов: обычный файл, каталог, специальный символ, специальный блок, FIFO и сокет (плюс разночтения); символические ссылки не фигурируют, потому что вы должны использовать lstat(), чтобы найти их.   -  person Jonathan Leffler    schedule 01.04.2010


Ответы (5)


Альтернативой является fstat(), если у вас уже открыт файл (поэтому у вас есть файловый дескриптор для него). Или lstat(), если вы хотите узнать о символических ссылках, а не о файле, на который указывает символическая ссылка.

Я думаю, что справочная страница преувеличивает стоимость; это не намного хуже, чем любой другой системный вызов, который должен преобразовать имя файла в индексный дескриптор. Это дороже, чем getpid(); это дешевле, чем open().

person Jonathan Leffler    schedule 01.04.2010
comment
Примечание на странице руководства о стоимости статистики не столько говорит об использовании чего-то другого, кроме статистики; это означает, что вы должны стараться избегать ненужных вызовов stat. - person Cascabel; 01.04.2010
comment
В самом деле... на самом деле, если вы посмотрите на трассировки некоторых Linux-программ, вы увидите довольно много вызовов статистики. - person jpalecek; 01.04.2010
comment
Типичная статистика процесса постоянно. Особенно те, которые обертывают или построены на слое поверх C. Они генерируют постоянные вызовы статистики, чтобы проверить, все ли так, как они ожидали, и т. д. Даже нажатие на вкладку на терминале автозаполнения генерирует кучу вызовов статистики. - person Matt Joiner; 22.07.2010

«Тип файла», который дает вам stat(), указывает, является ли файл обычным файлом или чем-то вроде файла или каталога устройства, среди прочего, таких как его размер и номер инода. Если это то, что вам нужно знать, то вы должны использовать stat().

Если вам действительно нужно знать тип содержимого файла, например. текстовый файл, изображение в формате JPEG, звук в формате MP3 — тогда у вас есть два варианта. Вы можете догадаться по расширению имени файла (если оно заканчивается на ".mp3", файл, вероятно, содержит звук в формате MP3), или вы можете использовать libmagic, которая на самом деле открывает файл и считывает часть его содержимого, чтобы выяснить, что это такое. Подход libmagic более затратный (если вы пытаетесь избежать stat(), вы, вероятно, также захотите избежать open()), но менее подвержен ошибкам (например, в случае, если файл ".mp3" на самом деле является изображением JPEG).

person Wyzard    schedule 01.04.2010

В Linux с некоторыми файловыми системами тип файла (обычный, символьное устройство, блочное устройство, каталог, канал, символическая ссылка, ...) хранится в структуре linux_dirent, в которой ядро ​​предоставляет записи каталога приложений через системный вызов getdents. . Если единственное, что вам нужно в структуре статистики, это тип файла, и вам нужно получить его для всех или многих записей каталога, вы можете использовать getdents напрямую (а не readdir) и попытаться получить тип файла из этого, используйте stat только в том случае, если вы обнаружили недопустимый тип файла в linux_dirent. В зависимости от шаблона использования файловой системы вашего приложения это может быть быстрее, чем использование stat, если вы используете Linux, но во многих случаях stat должен быть быстрым.

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

fstat всегда должен быть очень быстрым, так как ядро ​​уже должно иметь данные, которые вы запрашиваете, в ОЗУ, так как ему необходимо получить к ним доступ, чтобы файл был в открытом состоянии, и ядру не придется сталкиваться с проблемой. прохождения пути имени файла, чтобы увидеть, находится ли каждый компонент в ОЗУ или на диске и, возможно, читает в каталоге с диска (но, вероятно, не обязательно), только чтобы обнаружить, что у него есть данные, которые вы запрашиваете в ОЗУ.

При этом вызов stat для открытого файла должен быть быстрее, чем вызов для неоткрытого файла.

person nategoose    schedule 01.04.2010

Знаете ли вы о «волшебном» файле в системах *nix? Запросив файл из командной строки с чем-то вроде file myfile.ext, вы можете получить реальный тип файла.

Это делается путем чтения содержимого файла, а не просмотра его расширения, и широко используется в системах *nix (Linux, Unix, ...).

person Etamar Laron    schedule 01.04.2010
comment
Если stat() дорого, то можете себе представить стоимость запуска программы для определения типа файла? - person Jonathan Leffler; 01.04.2010
comment
(1) Я не говорил запускать программу. Я имею в виду, что определить тип файла можно по его первым байтам (сигнатуре), если помощнику действительно нужно знать тип. Это компромисс, который следует учитывать. (2) Но если расширение является надежным или достаточным, то его можно использовать, не открывая файл, как предлагалось ранее. Обратите внимание, что он сказал любую альтернативу. - person Etamar Laron; 01.04.2010
comment
Стоимость определения типа файла огромна по сравнению со статистикой. Также OP относится к типу файла unix, а не к типу mime. - person Matt Joiner; 22.07.2010

Если предполагается, что ваше приложение будет работать в системах Linux, почему бы вам не попробовать inotify(7). Это определенно быстрее, чем stating много файлов.

person Manish    schedule 21.01.2011