在 Mac OS X 上清除缓冲区缓存

Posted

技术标签:

【中文标题】在 Mac OS X 上清除缓冲区缓存【英文标题】:clear buffer cache on Mac OS X 【发布时间】:2010-10-02 08:27:27 【问题描述】:

有没有办法以编程方式清除 Mac 上的缓冲区缓存,最好用 C 语言?

基本上,我正在寻找 10.5(及更高版本)的 purge 命令的源代码。 编辑:我现在看到这是 CHUD 工具的一部分,似乎无法直接获得其源代码。但是,我仍在寻找一些代码来做同样的事情。

【问题讨论】:

你真正的目标是什么?是为了确保你写入文件的数据真的在磁盘上吗?如果是这样,那么请考虑 open() 调用中符合 POSIX 的 O_DSYNC 或 O_SYNC 选项。 哇,那是 5 年前的事了,但你还能帮我实现同样的目标吗?接受的答案看起来 gr8 但我不知道汇编,所以它对我来说有点没用:( 【参考方案1】:

我已经从 CHUD 框架中反汇编了有问题的函数 (_utilPurgeDiskBuffers)。该函数似乎不是很复杂,但由于我不是 MacOS 程序员,因此导入和调用的 sys API 对我来说没有多大意义。

API 做的第一件事是调用另一个函数,即_miscUtilsUserClientConnect_internal。这个函数似乎建立了与 CHUD 内核扩展的连接。 为此,它调用_getCHUDUtilsKextService,它试图通过使用从I/O 套件导入的IORegistryCreateIterator 枚举所有kexts 来定位CHUD 内核扩展。找到kext后,通过_ioserviceOpen打开。

此时我们与 CHUD kext 建立了连接(至少这是我从反汇编列表中的理解)。

最后拨打了IOConnectMethodStructureIStructureO,我猜这实现了真正的魔力。 在不知道一些内部细节或这个函数的签名的情况下,参数对我来说没有意义。

下面是反汇编代码:

__text:4B0157A7 lea     eax, [ebp+var_1C]
__text:4B0157AA mov     dword ptr [esp+14h], 0
__text:4B0157B2 mov     [esp+10h], eax
__text:4B0157B6 mov     [esp+0Ch], eax
__text:4B0157BA mov     dword ptr [esp+8], 0
__text:4B0157C2 mov     dword ptr [esp+4], 0Eh
__text:4B0157CA mov     [esp], edx
__text:4B0157CD call    _IOConnectMethodStructureIStr

请注意,var_1C 之前已清零。

希望你们中的一些人能更了解这些系统调用。如果您想了解更多信息,请告诉我。

更新: 为了帮助您入门,只需使用 IO 套件 SDK 中的 AppleSamplePCIClient.c 示例。这基本上完成了 CHUD 工具中的清除应用程序所做的工作。 您唯一需要更改的是最终_IOConnectMethodStructureIStr 调用的参数。从上面的反汇编列表中获取它们。因为我没有 Mac,所以我无法测试所有这些东西。

【讨论】:

我想做这个,但我不知道汇编,你能帮我弄清楚参数吗?【参考方案2】:

看来:

你可以使用 usr/bin/purge (输入 purge 在终端中)刷新磁盘 缓存(非活动内存),或者你可以这样做 从硬盘进行多次随机读取 做同样的事情

取自用户guns的comment。

【讨论】:

【参考方案3】:

您是否有兴趣关闭文件的缓存?根据您要实现的目标,它可能是另一种选择。 Good summary here.

UBC 可以通过运行 'purge' 来清除 它分配了大量内存 强制清除缓存。

fcntl(fd, F_GLOBAL_NOCACHE, 1)  

可用于关闭特定缓存 文件。这可以在任何过程中完成 之后可以关闭文件。

【讨论】:

我只是把它作为替代路线,不知道你在做什么。如果它不符合要求,请忽略它。只是有时,当你需要经常清除缓存时,可能是因为一开始就不应该缓存它。 我的印象是,即使像这样关闭缓存(使用 F_NOCACHE 或 F_GLOBAL_NOCACHE),如果页面缓存中已经有文件的页面,这些页面仍然会被使用。我尝试通过使用带有 direct=1 的 fio(1) 来测试这一点。这似乎证实了我的怀疑(在我的 MBP 中的主轴 HDD 上,我在随机读取时获得约 1200MB/s 的吞吐量,不是 SSD)。我已经用 dtruss 确认了 fio(1) 实际上正确调用了 fcntl。 在运行“sudo purge”并尝试相同的 fio(1) 调用之后,它要慢得多。所以是的,F_NOCACHE 似乎与 Linux 上的O_DIRECT 没有直接等价关系。【参考方案4】:

您可以多次使用sync(2)(如众所周知的成语sync; sync; sync)。我似乎找不到 purge 源代码,但它可能只是可用的 man 软件包的一部分 in 10.5.6 code

【讨论】:

purge 是 CHUD 的一部分,所以这就是为什么你找不到源 ;-) 那么,这是否意味着源不可用,或者只是隐藏? Keltia,这只会强制写入磁盘;它实际上并没有清除缓冲区缓存。 除了尝试反汇编或在 DTrace 下运行它之外,我看不出还有什么办法可以访问源代码。【参考方案5】:

当您没有想要模拟的工具的源代码时(就像这里的情况),有很多方法可以解决。

1/ 从您的 C 代码中,只需使用 system() 函数调用来调用该工具。只要没有可见效果(例如打开图形窗口),此方法就可以很好地工作。例如,您可以使用system("/path/to/purge -purgargs >/dev/null 2>&1");

2/ 对代码进行逆向工程以查看其实际执行情况。这有点棘手,因为它需要了解汇编语言、系统调用和许多其他知识。

3/ 联系开发人员以获取有关如何完成的提示。这不一定是“将代码发送给我,这样我就可以撕掉它并赚钱”的问题。您可以将其表述为“我有兴趣使用 purge 进行开发,但我不确定它到底是做什么的”或“我在运行代码时遇到了安全问题,除非我们知道,否则权力不会让我运行它正是它的作用”。然后你编写你的代码来做同样的事情。

我,如果可能的话,我只会使用选项 1(我天生就很懒 :-)。如果您要编写一个与 purge 竞争的工具(鉴于它是免费的,这将很难),选项 2 可能是最好的选择。

【讨论】:

我猜如果我去询问他们的一些专有源代码,Apple 不会有那么大的帮助。 不,我认为他们也不会,这就是为什么我说要更巧妙地表达它:-)无论如何,你不需要他们的代码(使用它可能会让你编码衍生作品/侵犯版权)。你只需要知道如何在概念上做到这一点。

以上是关于在 Mac OS X 上清除缓冲区缓存的主要内容,如果未能解决你的问题,请参考以下文章

text Mac Os X Mojave清除dns缓存

Mac OS X 声音输出

在GNU/Linux系统上清除缓冲区缓存

Mac OS X 上是不是有 dtrace ustack() 助手?

在 mac os 上执行程序时 libprotobuf 检查失败

如何清除Oracle中的所有缓存项