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