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

时间:2009-09-17 15:27:48

标签: filesystems kernel device-driver

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

myprogram / c [some_executable_here]

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

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

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

编辑:我正在寻找代码示例,了解如何最终实现此目标(或者至少指向我可以遵循的API)在Windows上执行此操作Linux操作系统。

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

3 个答案:

答案 0 :(得分:7)

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

$ strace -o/tmp/blah -f -eopen,read bash -c "cat ciao.txt"

运行请求的命令(包括它产生的子进程,由于-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)

这有点过于简单(您需要观看其他一些系统调用,例如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']

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

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

不幸的是,据我所知,其他一些Unix系统只提供这种设施,如果你是root用户(超级用户) - 例如在Mac OS X上,您需要通过sudo才能执行dtracedtruss等跟踪实用程序;我不知道Mac的strace直接端口,也没有其他方法可以在没有root权限的情况下执行此类任务。

答案 1 :(得分:5)

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

在Linux上,尝试使用lsof获取当前快照,并strace进行连续监控。您必须使用grep过滤输出。

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

[编辑]请参阅this page上的“如何运作”部分,开始在Windows上编写自己的工具。

答案 2 :(得分:0)

选项 -d ( - watchfd)was added in 2014进入 pv 以密切关注pid。

易于记忆,有助于调试。

pv --help
  -d, --watchfd PID[:FD]   watch file FD opened by process PID

例如,以他的名字观看一个过程。

pv -d `pgrep firefox`