仪器化是什么?

42

我听说过这个术语在日志记录中被频繁使用,但似乎找不到一个清晰的定义来解释它究竟是什么。

它只是一类更通用的日志记录/监控工具和活动吗?

请提供示例代码/场景,说明何时/如何应该使用仪器化。

6个回答

24

我编写执行工具。以下是我对它们的理解:

  • DLL重写。这是Purify和Quantify等工具所做的。此前有人回答说它们会在编译/链接后进行插装,但这是不正确的。Purify和Quantify会在第一次执行编译/链接周期后插装DLL,然后缓存结果,以便下次更快地使用。对于大型应用程序,对DLL进行分析可能非常耗时。这也存在问题——在1998-2000年间我工作的一家公司中,我们有一个大型的200万行应用程序,在插装期间会花费4个小时,并且其中2个DLL会在插装期间随机崩溃,如果任何一个失败,您都必须删除它们两个,然后重新开始。

  • 原地插装。与DLL重写类似,但不修改DLL,磁盘上的映像保持不变。当首次加载DLL(在启动期间或调用LoadLibrary(Ex)之后)时,适当地钩住DLL函数以执行所需任务。您可以在Microsoft Detours库中看到类似于此的技术。

  • 即时插装。类似于原地插装,但仅在首次执行方法时实际插装方法。这比原地插装更复杂,并延迟插装的惩罚,直到第一次遇到该方法。根据您所做的事情,这可能是好事或坏事。

  • 中间语言插装。这通常用于Java和.Net语言(C#、VB.Net、F#等)。语言被编译为中间语言,然后由虚拟机执行。虚拟机提供了一个接口(JVMTI用于Java,ICorProfiler(2)用于.Net),允许您监视虚拟机正在执行的内容。其中一些选项允许您在将中间语言编译为可执行指令之前修改中间语言。

  • 通过反射的中间语言插装。Java和.Net都提供反射API,允许发现有关方法的元数据。使用此数据,您可以动态创建新方法,并像前面提到的中间语言插装一样插装现有方法。

  • 编译时插装。此技术用于在编译期间向应用程序中插入适当的指令。这种方法并不常用,Visual Studio 的性能分析功能提供了此功能。需要全面重建和链接。

  • 源代码插装。此技术用于修改源代码以插入适当的代码(通常是条件编译,因此您可以将其关闭)。

  • 链接时插装。此技术仅在用跟踪分配器替换默认内存分配器时才真正有用。早期的例子是 1990 年代初的 Solaris/HP 上的 Sentinel 内存泄漏检测器。

各种原地和即时插装方法都存在危险,因为很难安全地停止所有线程并修改代码,而不会冒险需要访问由刚刚暂停的线程持有的锁的 API 调用 - 您不希望这样做,否则您将遇到死锁。您还必须检查是否有其他线程正在执行该方法,因为如果有,则无法修改它。

基于虚拟机的插装方法要容易得多,因为虚拟机保证您可以在那个点安全地修改代码。

  • (编辑-稍后添加的此项)IAT 钩子插装。这涉及修改与其他 DLL/共享库中链接的函数的导入地址表。这种类型的插装可能是最简单的方法,您不需要知道如何反汇编和修改现有二进制文件,或者用虚拟机操作码做同样的事情。只需使用您自己的函数地址修补导入表,并从您的钩子调用真实函数。在许多商业和开源工具中使用。

我想我已经涵盖了它们所有,希望对您有所帮助。


您在Memory Validator中使用哪种技术? - eckes
我们在 C++ Memory Validator 中使用 IAT hooking、in place instrumentation 和 intermediate language instrumentation。使用哪种方法以及如何使用取决于用户选择的选项所确定的特定任务。 - Stephen Kellett
当新软件安装到被检测的操作系统中时会发生什么。例如,一个新的apk被安装到被检测的安卓操作系统中。 - Krishna Oza

7

仪器化通常用于动态代码分析。

与日志记录不同,仪器化通常由软件自动完成,而日志记录需要人工智能插入日志记录代码。


你说它在哪里使用。你说它与日志记录有什么不同。但是,它究竟是什么?它和“给你的系统添加监控”完全一样吗? - Juan Perez
你说它在哪里使用。你说它与日志记录有什么不同。但是,它究竟是什么?它是否与“为系统添加监控”完全相同? - undefined

7
这是一种对代码进行必要处理以进行进一步分析的通用术语。尤其是对于像C或C++这样的语言,有像Purify或Quantify这样的工具可以分析内存使用情况、性能统计等。为了使这些分析程序正常工作,需要进行“instrumenting”步骤来插入计数器、数组边界检查等,这些由分析程序使用。请注意,在Purify/Quantify场景中,仪器化自动完成为后编译步骤(实际上,它是链接过程的一个附加步骤),您不需要修改源代码。对于动态或VM代码,这种操作可能较少必要(例如,Java提供了类似Quantify的OptimizeIt分析工具,但不需要特殊的链接),但这并不否定这个概念。

4

来自维基百科文章的摘录

在计算机编程背景下,仪器化指的是监视或测量产品性能水平、诊断错误和编写跟踪信息的能力。程序员通过代码指令实现仪器化,以监视系统中特定的组件(例如,指令可以输出日志信息以在屏幕上显示)。当应用程序包含仪器化代码时,可以使用管理工具进行管理。仪器化对于审查应用程序的性能是必要的。仪器化方法可以分为两种类型:源仪器化和二进制仪器化。


0
https://opentelemetry.io/docs/concepts/instrumentation/开始
为了使系统可观察,必须进行仪器化:也就是说,系统组件的代码必须发出跟踪、度量和日志。
无需修改源代码,您可以使用自动仪器化从应用程序收集遥测数据。
因此,仪器化简单地意味着向系统添加监控功能。可以通过简单地添加一行print("something happened")代码("手动"方式),或者通过一些在幕后运行并读取时间戳、堆栈跟踪、硬件调用等的程序("自动"方式)来实现。
似乎很多人专门使用"自动仪器化"来进行仪器化。

-2

无论维基百科如何说,IT行业中没有标准/广泛认可的定义来描述代码仪表化

请注意,仪表化是从仪器派生出来的名词,其含义非常广泛。

代码”也是IT中的一切,我的意思是-数据、服务、一切。

因此,代码仪表化是一组应用程序,它是如此广泛...不值得给它一个单独的名称;-)。

这可能就是为什么这篇维基百科文章只是一个简短的介绍。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接