1

是否有可以确定文件类型的 stat (在大多数 Unix 系统上都可以找到)的替代方法?手册页说调用 stat 很昂贵,我需要在我的应用程序中经常调用它。

4

5 回答 5

7

另一种方法是fstat()如果您已经打开了文件(因此您有一个文件描述符)。或者lstat(),如果您想了解符号链接而不是符号链接指向的文件。

我认为手册页夸大了成本;它并不比任何其他必须将文件名解析为 inode 的系统调用差多少。它比getpid(); 它的成本低于open().

于 2010-04-01T13:38:37.893 回答
3

为您提供的“文件类型”stat()是文件是常规文件还是设备文件或目录之类的东西,以及它的大小和 inode 编号等。如果这是您需要知道的,那么您必须使用stat().

如果您真正需要知道的是文件内容的类型——例如文本文件、JPEG 图像、MP3 音频——那么你有两个选择。您可以根据文件扩展名进行猜测(如果它以“.mp3”结尾,则该文件可能包含 MP3 音频),或者您可以使用libmagic,它实际上会打开文件并读取其中的一些内容以找出它是什么。libmagic 方法更昂贵(如果您想避免stat(),您可能也想避免open()),但不太容易出错(例如,如果“.mp3”文件实际上是 JPEG 图像)。

于 2010-04-01T13:44:05.027 回答
3

在具有某些文件系统的 Linux 下,文件类型(常规、字符设备、块设备、目录、管道、符号链接等)存储在 linux_dirent 结构中,这是内核通过 getdents 系统调用提供应用程序目录条目的内容. 如果您需要的 stat 结构中唯一的东西是文件类型,并且您需要为目录的所有或许多条目获取它,您可以直接使用 getdents(而不是 readdir)并尝试从中获取文件类型,仅当您在 linux_dirent 中发现无效文件类型时才使用 stat。根据您的应用程序的文件系统使用模式,如果您使用的是 Linux,这可能比使用 stat 更快,但在许多情况下 stat 应该很快。

Stat 的速度主要与定位磁盘上要求的数据有关。如果您正在遍历一个目录递归地统计所有文件,那么每个 stat 最终应该总体上相当快,因为​​在您通过先前调用 stat 向内核询问它之前,获取数据 stat 需要的大部分工作最终都被缓存了. 另一方面,如果您统计在系统中随机分布的相同数量的文件,那么内核可能必须为您要调用 stat 的每个文件从磁盘读取几个目录。

fstat 应该总是非常快,因为内核应该已经在 RAM 中拥有您要求的数据,因为它需要访问它以使文件处于打开状态,并且内核不必遇到麻烦遍历文件名的路径以查看每个组件是在 RAM 中还是在磁盘上,并可能从磁盘中读取目录(但可能不必),只是发现它在 RAM 中具有您要求的数据。

话虽如此,在打开的文件上调用 stat 应该比在未打开的文件上调用它更快。

于 2010-04-01T23:41:08.910 回答
1

您知道 *nix 系统上的“魔法”文件吗?通过从命令行查询文件,file myfile.ext您可以获得真正的文件类型。

这是通过读取文件的内容而不是查看其扩展名来完成的,并且广泛用于 *nix (Linux, Unix, ...) 系统。

于 2010-04-01T13:37:57.817 回答
1

如果您的应用程序希望在 Linux 系统上运行,您为什么不尝试 inotify(7)。它肯定比stating 许多文件要快。

于 2011-01-21T05:13:16.313 回答