在 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 上清除缓冲区缓存的主要内容,如果未能解决你的问题,请参考以下文章
Mac OS X 上是不是有 dtrace ustack() 助手?