对于黑盒可执行文件,您可以自动执行的最简单和最可靠的事情可能是查看它们的 CPU 使用情况。当它们完成加载时,它们的所有线程应该(大部分)空闲,如果它们等待具有非无限超时的事件,可能会偶尔醒来。(以及来自鼠标移动等其他 GUI 事件)。
确保等待足够长的时间来检测磁盘 I/O 上阻塞与等待用户输入阻塞之间的区别。(在类 Unix 操作系统上,这是 Disk-sleep 和 Sleep 之间的区别,如's 进程列表中的D
vs.所示。)S
top
如果您不想依赖操作系统来检测磁盘睡眠与常规睡眠,只需等待比最大磁盘 I/O 请求服务时间长几倍(~= 几倍磁盘延迟,如果进程延迟则更低) under test 是唯一进行 I/O 的进程)。如果黑盒进程在该时间间隔内没有使用任何 CPU 时间,您可以假设它已完成加载并正在屏幕上显示文件。
当然,正如@Ped7g 指出的那样,它可能没有解析整个文件。例如,当用户滚动浏览大型 PDF 时,它可能会按需延迟加载。观察 CPU 时间应该是一种合理的方法,可以在以编程方式向进程发送 page-down 命令后检测进程何时完成更新。
我认为您应该能够从中获得良好的可靠结果。如果您想可靠地确定进程已完成加载,而无需等待最坏的情况,您可能需要考虑多个输入的启发式方法,例如系统 I/O 性能或未完成的磁盘 IO 请求。
正如评论中所讨论的,在文件描述符上寻找到达 EOF 的过程对于这个目的是不可靠的(它可能会映射它)。我会把它留在这里,以防它对任何人都有趣或有用,但为了您的使用,您可能希望完全忽略它。充其量,您可以将其用作启发式方法的输入,以决定何时完成加载进程。
在大多数操作系统上,进程都有一些工具可以跟踪其他进程。在 Linux 上,主要的是 ptrace API。诸如strace
使用它来跟踪系统调用之类的命令。我相信 Windows 也有类似的东西,我认为 OS X 也有。
因此,您可以在 PDF 上查找 open() 系统调用以找到正确的 fd,然后在其上查找 mmap、read() 和 close() 系统调用。如果 read() 返回 0,它在 EOF。如果它在没有 mmap 的情况下关闭,则使用它完成该过程(除非它再次打开它,或者出于某种原因使用 dup() 或 dup2())。
您可以解析 strace 的文本输出,或者自己使用 ptrace API。
或者,在 Linux 上,您可以查看/proc/<PID>/fdinfo/<FD>
. 其他操作系统可能具有类似的工具来查看打开文件描述符/文件句柄的文件位置。
例如,我碰巧evince
打开了显示 PDF。在`/proc/
$ ll /proc/4241/fd
...
lr-x------ 1 peter peter 64 Oct 21 06:43 14 -> /f/p/docs/agner_fog.microarchitecture.pdf # is anyone really surprised this is the PDF I had open? :P
...
$ ls -lL /proc/4241/fd/14 # follow the symlink to see the file size
-rw-rw-r-- 1 peter peter 2078709 Feb 4 2016 /proc/4241/fd/14
$ m /proc/4241/fdinfo/14 # alias for less
pos: 2078709
flags: 0100000
mnt_id: 49
这证实了我的猜测,当它完成读取文件时,evince 的文件位置将位于 EOF。您可能应该等待几毫秒并再次检查,以防被测软件再次循环文件。