使用stat()获取文件类型的替代方法?

时间:2010-04-01 13:21:41

标签: c system-calls

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

5 个答案:

答案 0 :(得分:7)

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

我认为手册页夸大了成本;它并不比任何其他系统调用更糟糕,它必须将文件名解析为inode。它比getpid()更昂贵;它比open()便宜。

答案 1 :(得分:3)

stat()给出的“文件类型”是文件是常规文件还是类似设备文件或目录,以及其大小和inode编号等。如果这是您需要知道的,那么您必须使用stat()

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

答案 2 :(得分:2)

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

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

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

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

答案 3 :(得分:1)

您是否了解* nix系统上的“神奇”文件?通过使用类似file myfile.ext的命令行查询文件,您可以获得真实的文件类型。

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

答案 4 :(得分:1)

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