为了简短说明为什么我需要这个,
我目前正在通过stat(2)
进行检测。我无法控制文件描述符(由于注入代码来替换syscall时,其他描述符可能会用尽它),所以我不能使用fstat(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不会发生任何事情。