在不知道文件描述符的情况下检测文件大小不为零的最快方法是什么?

时间:2019-06-23 16:35:49

标签: c macos file filesize

为了简短说明为什么我需要这个, 我目前正在通过stat(2)进行检测。我无法控制文件描述符(由于注入代码来替换syscall时,其他描述符可能会用尽它),所以我不能使用fstat(2)(更快)。我需要多次进行此检查,所以有没有更快的方法来做同样的事情? 我正在不存在父子关系的不同进程中检查同一文件。

2 个答案:

答案 0 :(得分:2)

您可能应该自己进行基准测试。

我测量过

//Real-time System-time
272.58 ns(R)    170.11 ns(S)  //lseek
366.44 ns(R)    366.28 ns(S)  //fstat
812.77 ns(R)    711.69 ns(S)  //stat("/etc/profile",&sb)

在我的Linux笔记本电脑上。它在两次运行之间波动很小,但是lseek通常比fstat快一纳秒,但是您还需要一个fd,open的成本很高,约为1.6µs,因此stat可能是适合您的情况的最佳选择。


正如tom-karzes所指出的,stat应取决于路径中目录组件的数量。我在PATH_MAX长的“ /foo/foo/.../foo”目录中进行了尝试,然后开始了解80µs

答案 1 :(得分:0)

了解您要搜索的文件系统的最有效方法是,打开关联的块设备并搜索(逐块)inode表,并从那里的inode检查实际大小(打开块设备,因此您从内存映像而不是从磁盘获取inode)。这使您可以快速而肮脏地获取文件系统的所有零长度索引节点。缺点是您首先需要获取文件系统的信息,然后直接访问块设备,这通常是非根进程所禁止的。之后,您必须搜索文件系统以获取所涉及文件的名称,以防万一您需要对这些文件执行某些操作。

顺便说一句,您的假设无法在另一个线程的共享文件描述符上使用fstat(2)是错误的,因为stat系统调用对打开的文件描述符进行操作,并且不对文件做任何操作-这是非阻塞的--并且系统保证在访问stat结构时索引节点已锁定。

在这种情况下,使用lseek(2)的方法无效,因为它实际上将文件指针移到文件末尾,然后又移回了保存的位置,并且这需要两个系统调用做并撤消移动,如果将文件指针放在另一个位置,而另一个线程使用另一个系统调用(在两个线程之间执行write(2)),则会发生许多竞争情况。< / p>

Unix(包括所有posix系统linux,bsd等)保证无阻塞的系统调用(如stat(2)是原子的,在进程(或线程)运行时阻塞文件的inode正在执行系统调用。因此,在您的stat(2)系统调用获取数据时,没有其他线程可以使用该文件。即使在阻塞调用中,Unix也保证对同一描述符进行的不同系统调用将被链接起来执行,并且进程/线程将不得不等待,直到stat(2)系统调用结束。

fstat(2)上的问题是,它必须解决所有路径元素,直到到达文件的最后一个inode(这是存储文件长度的位置)为止,并且这是一个完成的。一个方面。在到达最终索引节点之前,不会对最终索引节点进行锁定(实际上,直到我们到达它为止,它是未知的,因此直到完成namei()解析之前,我们才能阻止它)作为原始stat(2)求解。

结论

在没有担心数据损坏的情况下,将stat(2)其他线程文件描述符一起使用。请不要犹豫,因为在收集stat信息时文件的inode不会发生任何事情。