我有兴趣拦截与文件系统相关的所有系统调用,而不是让我自己的代码运行.例如,调用creat,write,close,lseek,getcwd等.我的目标是创建一个像execve这样的函数,它捕获从生成的程序到调用进程管理的内存文件系统中的所有文件I / O.这样,调用程序就可以在没有文件系统开销的情况下检查输出.
我的用例是使用没有API或库的大型数值模拟程序.这些程序仅通过输入和输出文件进行通信.如果这些文件很大,那么运行时的大部分时间只需要执行I / O.在某些拥有超级用户权限的计算机上,可以设置一个存在于RAM中的文件系统(例如Linux上的tmpfs),但是没有超级用户权限,或者以某种方式配置的机器是不可能的.
我知道使用LD_PRELOAD可以调用自定义代码而不是libc中的函数.但是,这仅适用于动态链接程序,并且它不回答如何在调用程序(我想要托管内存文件系统)和被调用者之间执行IPC的问题.这种方法的问题是如何最好地执行IPC.我应该使用管道,unix域套接字还是一些共享内存?
我也把ptrace看成是拦截系统调用的一种方法.这似乎可能有用,但我对这种方法有两个问题.首先,如何防止实际的系统调用发生(而不是像我在一些例子中看到的那样修改系统调用的参数).第二,ptrace是否允许高性能读取被调用者的内存空间?
最佳答案 使用LD_PRELOAD,您可以让被拦截的代码在被调用者的内存空间中运行.使用库构造函数(__attribute __((constructor))),您可以在库首次启动时运行您选择的代码,例如: mmaping您的虚拟文件系统并初始化它.
然后,当您使用预加载的库拦截调用时,库的函数在目标进程中运行,可以访问构造的文件系统 – 不需要IPC.
如果调用进程必须管理文件系统,则会产生与之通信的开销.我建议在子进程中映射文件系统的重要部分(可能作为共享内存区域),而是使用子进程中的监听器来监视来自父进程的文件系统更改(适当锁定文件系统操作).您可以使用简单的管道进行更改通知,因为带宽要求较低.
另请查看Plash,这是一个半虚拟化系统,通过提供修改后的Glibc来对文件系统进行访问.