Linux Kernel 5.3
考虑fstat
定义为的系统调用int fstat(int fd, struct stat *statbuf);
。fstat
ext4 上的系统调用是否需要磁盘访问?
我做了一些相关的研究并找到了一些信息。系统调用的内核入口点是函数vfs_statx_fd
。它的实现如下所示:
int vfs_statx_fd(unsigned int fd, struct kstat *stat,
u32 request_mask, unsigned int query_flags)
{
struct fd f;
int error = -EBADF;
if (query_flags & ~KSTAT_QUERY_FLAGS)
return -EINVAL;
f = fdget_raw(fd);
if (f.file) {
error = vfs_getattr(&f.file->f_path, stat,
request_mask, query_flags);
fdput(f);
}
return error;
}
所以我们这里得到的是unsigned int fd
用户传递给系统调用的实际文件描述符,用于查找指向struct file
。其定义的关键部分是
struct file {
//...
struct path f_path;
struct inode *f_inode; /* cached value */
//...
}
所以我们基本上有struct file
代表一个打开的文件,并且该结构包含对dentry
和 的引用inode
如果我们有一个打开的文件描述符,我们是否可以仅从内存中获取所有统计信息,从而避免昂贵的磁盘访问?
更新:我尝试在free && sync && echo 3 > /proc/sys/vm/drop_caches && free
调用之前刷新内核缓存syscall
,它不会影响 stat 系统调用的时间。所以我倾向于认为不需要磁盘访问。
答案1
在 Ext4 文件系统上,从以下位置开始的函数图vfs_statx_fd
是
0) | vfs_statx_fd() {
0) | __fdget_raw() {
0) 0.225 us | __fget_light();
0) 0.775 us | }
0) | vfs_getattr() {
0) | security_inode_getattr() {
0) | selinux_inode_getattr() {
0) | __inode_security_revalidate() {
0) | _cond_resched() {
0) 0.216 us | rcu_all_qs();
0) 0.575 us | }
0) 0.945 us | }
0) | inode_has_perm() {
0) 0.356 us | avc_has_perm();
0) 0.709 us | }
0) 2.223 us | }
0) 2.808 us | }
0) | vfs_getattr_nosec() {
0) | ext4_file_getattr() {
0) | ext4_getattr() {
0) 0.203 us | generic_fillattr();
0) 0.600 us | }
0) 1.040 us | }
0) 1.502 us | }
0) 4.854 us | }
0) 6.913 us | }
查看所有这些函数的实现表明,没有提供磁盘 I/O。正如您猜测的那样,数据来自缓存的索引节点。
也可以看看联机fstat(2)
帮助页其中提到:
笔记:出于性能和简单性的原因,
stat
结构中的不同字段可能包含系统调用执行期间不同时刻的状态信息。例如,如果st_mode
或st_uid
被另一个进程通过调用更改chmod(2)
或者chown(2)
,stat()
可能旧的st_mode
和新的一起还st_uid
,或者旧的st_uid
和新的一起还st_mode
。
(尽管这更多地与锁定有关,而不是与缓存有关)。
对于某些其他文件系统,AT_STATX_FORCE_SYNC
可以包含在查询标志中以强制远程同步; Ceph、FUSE、NFS 和 VirtualBox 来宾共享文件夹支持此功能。