当我调用 fseek() 时,在低级别会发生啥?

Posted

技术标签:

【中文标题】当我调用 fseek() 时,在低级别会发生啥?【英文标题】:What happens at a low level when I call fseek()?当我调用 fseek() 时,在低级别会发生什么? 【发布时间】:2015-08-31 13:50:54 【问题描述】:

当在 C 中调用 fseek() 或在任何现代语言(如 Python 或 Go)中对文件对象调用 seek() 时,在非常低的级别会发生什么?

操作系统或硬盘实际上是做什么的? 读什么? 会产生什么开销? 块大小如何影响这种开销?

编辑添加:

给定块大小为 4KB 的 NTFS,寻找 4096 字节会比读取 4096 字节产生更少的 IO 开销吗?

第二次编辑:

如有疑问,请根据经验进行。

在 1.5GB 文件中使用一些简单的 Python 代码:

按顺序读取 4096:21.2 寻求 4096(相对):1.35 求 4096(绝对):0.75(有趣) 每隔 4096(相对)搜索和阅读一次:21.3 搜索并阅读每三分之一 4096(绝对):21.5

平均时间以秒为单位。硬件是一台不起眼的 PC,带有运行 Windows XP 的 SATA 驱动器。

这非常令人失望。我有几 GB 的文件,我必须几乎不间断地阅读这些文件。文件中大约 66% 的 4KB 块是无趣的,我提前知道它们的偏移量。

最初,我认为重写所涉及的遗留代码可能是一个大胜利,因为它现在一次通过文件顺序读取 4096 个字节。假设 Win32 Python 没有在某些基本方面被破坏,合并搜索对于非随机读取没有任何优势。

【问题讨论】:

回答您的问题有点困难,因为“处于非常低的级别”实际上可能意味着很多事情......从硬盘驱动器可能必须进行的读取磁头移动到量子机械、磁盘控制器逻辑、文件系统簿记逻辑等。所有这些可能又取决于进一步的因素:你有硬盘驱动器(移动部件)还是 SSD(没有移动部件)?您使用的是什么文件系统?什么操作系统? 只是为了寻找,可能什么都没有。内核很可能缓存了文件的大小,并且可以在不执行任何 I/O 的情况下成功或失败查找。 我实际上几乎包括在我最初的问题中,我对物理头部运动不感兴趣。但是,我不想排除任何影响性能的事情。电子和磁通量水平?不。头部运动来阅读?是的。 【参考方案1】:

这在很大程度上取决于当前条件。通常, fseek() 仅更改流的状态(设置当前位置,或者如果参数错误则返回错误)。但是 - fseek() 刷新缓冲区,这可能会导致挂起的写操作。如果文件是 UTF8 文件并且启用了翻译,则从 fseek() 调用的 ftell() 需要读取文件的该部分以正确计算偏移量。如果启用 CRLF 转换,它也会引发读取操作。但是在纯二进制文件且没有挂起的写操作的情况下, fseek() 只是在流中设置位置,不需要转到较低级别。更多详情请参见CRT源代码。

【讨论】:

以上是关于当我调用 fseek() 时,在低级别会发生啥?的主要内容,如果未能解决你的问题,请参考以下文章

如果 fseek 中的给定偏移量超出最后一个字符会发生啥

我想描述啥计算机科学主题?

在 C 中通过引用传递时会发生啥?

当我在 NULL 对象指针上调用成员函数时会发生啥? [复制]

当我在 NULL 对象指针上调用成员函数时会发生啥? [复制]

当我在严格的客户端集合上调用更新/插入时会发生啥?