使用 hdiutil,您可以将磁盘映像挂载到特制的 HTTP 服务器上,但您无法控制操作系统缓存,并且 I/O 缓慢不会细化。我会建议两种非网络解决方案。
在 I/O 系统调用中插入缓慢
您可以进行减慢 I/O 系统调用,例如通过 DYLD_INSERT_LIBRARIES。这种方法很简单,这是我首先要尝试的。
您只需使用 read(2) 和 pread(2) 实现创建一个库,例如:
/* slow.c */
#define SLEEP_TIMESPEC {0, 25000000} // 25ms
ssize_t
read(int fildes, void *buf, size_t nbyte) {
struct timespec s = SLEEP_TIMESPEC;
(void) nanosleep(&s, NULL);
return (ssize_t) syscall(SYS_read, fildes, buf, nbyte);
}
ssize_t
pread(int d, void *buf, size_t nbyte, off_t offset) {
struct timespec s = SLEEP_TIMESPEC;
(void) nanosleep(&s, NULL);
return (ssize_t) syscall(SYS_pread, d, buf, nbyte, offset);
}
您可能还需要实现readv(2)。您只需将此 C 代码编译为共享库并设置 DYLD_INSERT_LIBRARIES 以在运行程序之前加载此库。您可能还需要定义DYLD_FORCE_FLAT_NAMESPACE。见dyld(1)。
clang -arch i386 -arch x86_64 -shared -Wall slow.c -o slow.dylib
(该库是通用编译的,因为我在磁盘上的 AIR 应用程序实际上是 i386,而不是 x86_64)。
要测试库,只需执行以下操作:
env DYLD_INSERT_LIBRARIES=slow.dylib DYLD_FORCE_FLAT_NAMESPACE=1 cat slow.c
您可能想尝试为cat 使用高于 25 毫秒的值,例如1 秒可以内联为{1, 0}。同样,您应该从命令行启动您的应用程序:
env DYLD_INSERT_LIBRARIES=slow.dylib DYLD_FORCE_FLAT_NAMESPACE=1 path/to/YourApp.app/Contents/MacOS/YourApp
这会减慢每次读取调用(即使通过更高级别的 API)。但是,某些读取操作不会受到影响(例如mmap(2)),您可能希望减慢某些文件的 I/O 而不是其他文件的 I/O。后一种情况可以通过捕获open(2) 来处理,但需要更多工作。
每次读取访问 25 毫秒足以使任何 AIR 应用程序明显变慢。当然,您应该根据需要调整此值。
使用较慢的文件系统
或者,您可以实现一个 Fuse 插件。如果您从 LoopbackFS(C 或 ObjC)开始,这尤其容易。
确实,您可以非常轻松地在readFileAtPath:userData:buffer:size:offset:error: 方法或loopback_read 函数中调用nanosleep(2)。