Som*_*ame 5 linux filesystems c files linux-kernel
Linux Kernel 5.3
考虑fstat定义为的系统调用int fstat(int fd, struct stat *statbuf);。ext4 上的fstat系统调用是否需要磁盘访问?
我做了一些与它相关的研究并找到了一些信息。系统调用的内核入口点是函数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;
}
Run Code Online (Sandbox Code Playgroud)
所以我们在这里得到的unsigned int fd是用户传递给系统调用的实际文件描述符 which 用于查找指向struct file. 其定义的关键部分是
struct file {
//...
struct path f_path;
struct inode *f_inode; /* cached value */
//...
}
Run Code Online (Sandbox Code Playgroud)
所以我们基本上有struct file代表一个打开的文件,并且结构包含对dentry和的引用inode
如果我们有一个打开的文件描述符,我们可以从内存中获取所有统计信息,从而避免昂贵的磁盘访问,这是真的吗?
更新:我尝试free && sync && echo 3 > /proc/sys/vm/drop_caches && free在调用之前使用right刷新内核缓存,syscall并且它没有影响 stat 系统调用的时间。所以我倾向于认为不需要磁盘访问。
上的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 | }
Run Code Online (Sandbox Code Playgroud)
查看所有这些函数的实现表明没有提供磁盘 I/O。正如您猜测的那样,数据来自缓存的 inode。
另请参见该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 来宾共享文件夹上受支持。