stat() 的调用流程是什么?

2021-03-01 12:48:40 +08:00
 abersheeran

最近在写代码的时候发现一个问题,把 Python 的 os.stat 丢到线程池里跑、直接单线程跑,性能差距相当之大。并且无论是很差劲的机械硬盘、不错的机械硬盘或者 SSD,性能差距比例基本一致。

于是对 stat 的调用逻辑产生了好奇,谷歌、必应查阅了一番资料之后也没有讲这个事的文章。所以来问问大家。

1247 次点击
所在节点    程序员
7 条回复
des
2021-03-01 12:57:41 +08:00
os 缓存的原因吧?
liuxu
2021-03-01 13:16:29 +08:00
bleepbloop
2021-03-01 13:29:53 +08:00
线程池跑的话也有上下文切换的开销吧,但不知道有多少
abersheeran
2021-03-01 14:09:28 +08:00
@des 我首先对大量不同的文件进行了测试,再对这些文件每个重复调用了十次和百次。如果存在缓存,耗时的增长不应该是实践结果所展示的线性增长。

我非常好奇调用过程。

@liuxu 我从未阅读过 Linux 内核代码。虽然这个函数我知道它干了什么,但是那些 flag 不知道什么意思,我对调用过程还是没理解。相比读写文件来说,stat 的磁盘 IO 为什么这么小?
liuxu
2021-03-01 15:28:19 +08:00
@abersheeran 文件存储在文件系统中,分为属性存储区(inode)和数据存储区(block),stat 只需要读属性存储区

不需要读过 linux 内核源码,遇到什么查什么而已,把它当做 helloworld 读就行,像我给的这个链接,你不需要搞清楚 flag 是什么意思,只需要知道它们会被填充到 stat 数据结构,并看看调用了哪些方法,根据方法并大概可以知道干了什么,不知道的跟进去看看就知道了

例如给你发的这个链接,vfs_statx(),根据名字你可以知道 linux 读取文件信息是通过 linux vfs 虚拟文件系统层拿的文件信息
它内部调用了 user_path_at(),可以知道它读取了文件路径,都不需要往里面看
然后调用了 vfs_getattr(),是通过 vfs 层读取了文件 attr
还调用了 real_mount(),那到了当前 mount 数据
...

然后你可能还想知道 user_path_at(),会发现最后调用了 filename_lookup(),然后你再分析它如何那文件信息的,最底层一般是汇编实现,可读性不高,不用太钻,你非要钻也行,无非就是花几天几周几个月而已,你掂量掂量看看值不值就行了


顺便提一下,c 语言不像现代高级语言,会返回一个对象,搞底层的 c 一般不会这么玩,一般会创建好数据结构,把指针传给个函数,让函数内部操作填充这个数据结构,最后返回 int 型状态信息,所以你会看到 vfs_statx()返回 int,而参数 stat 才是真正返回给调用层的数据结构

如果你非要知道 flag 的是,拿 flag 查 google 一定可以查出来,但是我给你了,你就往旁边一扔说未阅读过 Linux 内核代码,你对其他人给你带来的帮助给人感觉持有消极态度

看不懂就别看了,你目前的能力没法满足你的好奇心,过几年再看吧
abersheeran
2021-03-01 15:58:18 +08:00
@liuxu 我不觉得我的态度消极。你发的链接我再三看了,你说的这三个函数,你可能觉得你看函数名就知道干什么的,但是我是压根不知道它们干了啥,我是通过网站的点击跳转功能一层层看的,但是看到最后从 path.dentry 里拿 inode 节点跳一层,赋值给 stat 。我人都傻了,又调回去看。磁盘读写这个发生在哪儿我完全没看到,或者说没看懂。所以我才会说“我对调用过程还是没理解”。你现在回复说了 stat 只需要读属性存储区,我才明白是什么意思。

总之感谢你的回复。又学到了😀
joApioVVx4M4X6Rf
2021-03-01 16:00:43 +08:00
@liuxu 大佬,求推荐几本不错的技术书。谢谢大佬

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/757225

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX