观察文件系统read()I/O的进程(和子进程)的最佳方法是什么?

Gar*_*ren 3 filesystems kernel device-driver

我想开发一个像这样工作的命令行程序:

myprogram/c [some_executable_here]

其中启动了用户指定的命令并"监视"了读取I/O的进程(以及任何子进程)以及该程序何时退出,打印"已读取"的文件列表(最终导致读取()系统调用).

我最初的实现操作系统是Windows,但我也想在Linux上做同样的事情.

到目前为止我看到的所有FileSystem类似手表的API都是为了观看目录(或单个文件),而不是进程,所以我不确定最好的方法是什么.

编辑:我正在寻找如何最终实现这个(或至少指向我可以遵循的API指针)的代码示例,以便在Windows和Linux上执行此操作.

另外要明确的是,它不能使用类似于OpendFilesView,procmon或grepping来自某些系统级工具的字符串的方法,这些方法无法通过ID(以及任何子进程)从其执行的开始和结束来明确地识别进程; IOW通过搜索"foo.exe"并获取错误信息,不会出现任何计时问题和误报的可能性.

Ale*_*lli 7

在Linux上,我肯定会使用strace它 - 它简单而强大.例如:

$ strace -o/tmp/blah -f -eopen,read bash -c "cat ciao.txt"
Run Code Online (Sandbox Code Playgroud)

运行请求的命令(包括它产生的子进程,由于-f),并留下/tmp/blah(本例中为120行),详细说明这些进程所做的所有打开和读取调用及其结果.

之后您需要进行一些处理,以根据需要提取已成功读取的文件集; 例如,使用Python,您可以:

import re

linere = re.compile(r'^(\d+)\s+(\w+)\(([^)]+)\)\s+\=\s*(.*)$')

def main():
  openfiles = dict()
  filesread = set()
  with open('/tmp/blah') as f:
    for line in f:
      mo = linere.match(line)
      if mo is None:
        print "Unmatched line %r" % line
      pid, command, args, results = mo.groups()
      if command == 'open':
        fn = args.split(',', 1)[0].strip('"')
        fd = results.split(' ', 1)[0]
        openfiles[fd] = fn
      elif command == 'read':
        if results != '0':
          fd = args.split(',', 1)[0]
          filesread.add(openfiles[fd])
      else:
        print "Unknown command %r" % command
  print sorted(filesread)
Run Code Online (Sandbox Code Playgroud)

这有点过于简单(您需要观看其他一些系统调用,例如dup&c),但我希望,它显示了所需工作的要点.在我的例子中,这发出:

['/lib/libc.so.6', '/lib/libdl.so.2', '/lib/libncurses.so.5',
 '/proc/meminfo', '/proc/sys/kernel/ngroups_max',
 '/usr/share/locale/locale.alias', 'ciao.txt']
Run Code Online (Sandbox Code Playgroud)

所以它也算作"读取"那些为了获得动态库和c而不仅仅是"数据文件"......在系统调用级别,这几乎没有区别.我想你可以过滤掉非数据文件,如果那就是你需要的.

我觉得strace这样的目的非常方便,如果我的任务是在Windows上做同样的工作,我的第一次尝试是去StraceNT - 不是100%兼容,当然底层的系统调用名称和c有所不同,但我想我可以解释我的Python代码中的这些差异(准备和执行strace命令,并对结果进行后处理).

不幸的是,一些其他的Unix系统,据我所知,只有当你是root(超级用户)提供这种设施-例如,在Mac OS X,你需要通过去sudo为了执行这样的跟踪公用事业dtracedtruss; 我不知道straceMac 的直接端口,也没有其他方法可以在没有root权限的情况下执行此类任务.


Aar*_*lla 5

尝试" 进程监视器 "(procmon.exe)它允许指定一个过滤器(要监视的进程的名称).然后它将列出所述文件上的所有文件和操作.

在Linux上,尝试lsof使用当前快照和strace连续监视.您必须使用过滤输出grep.

所有这些工具都会检查流程结构(即操作系统用来管理流程的数据结构)并枚举那里提到的句柄/文件描述符.这不是文件系统API的函数,而是进程管理API的函数.

[编辑]请参阅此页面上的"如何工作"部分,开始在Windows上编写自己的工具.