有人知道dtrace
用于跟踪malloc
的功能/机制吗?我正在尝试分析一段代码,我可以借助调试器和一些命令行脚本来完成该代码,即:
sudo dtrace -n "pid`pgrep Mail | head -n 1`::malloc:entry { @sizes=quantize(arg0); }"
给我类似的东西
dtrace: description 'pid31411::malloc:entry ' matched 4 probes
^C
value ------------- Distribution ------------- count
-1 | 0
0 | 214
1 | 7
2 | 191
4 | 1054
8 |@@@@ 15992
16 |@@@@@@@@@@@@ 44569
32 |@@@@@@@@@@ 37003
64 |@@@@ 15426
128 |@@@@ 15695
256 |@ 2616
512 |@ 1967
1024 |@ 1891
2048 |@@ 6010
4096 | 523
8192 | 43
16384 | 110
32768 | 19
65536 | 0
131072 | 69
262144 | 0
但这对我来说真的很乏味。我想知道如何从代码中以编程方式做到这一点。
答案 0 :(得分:2)
我认为您正在错误地解决问题。您的示例显示了在过程和函数的任意组合中对任意参数的相当复杂的解释-能够在单行中完成而无需修改自己的程序,这是非常强大的。尝试让自己的代码执行相同的分析没有任何意义:例如,如果您想要线性标度而不是对数标度,该怎么办?重新实现lquantize()吗?
专注于编写所需的代码,然后让DTrace进行性能分析。
编辑以回复第一条评论。
您给出的示例的执行路径非常circuit回。从广义上讲,dtrace(1)
请求内核修改malloc
的序言,以便在进入时,调用线程将陷阱捕获到DTrace内核模块。在那里,在将控制权返回到检测到的线程之前,在每个CPU缓冲区内聚合数据。 dtrace
会定期通过libdtrace
来请求ioctl(2)
内核的每CPU缓冲区的快照。合并这些缓冲区,然后呈现您看到的图形也是libdtrace
执行的功能。在macOS上,libdtrace
API是私有的,其中包括与内核交换的记录的格式。因此,即使只是简单的示例,也要重用任何这种基础结构,都是“用大锤砸破螺母”。
进一步的考虑是,您将添加需要调试和维护的代码。如果您的代码足够复杂以至于需要自己进行检测,那么似乎有一天,您可能会考虑使用calloc()
,realloc()
和mmap()
。也许您可能还想从您自己的代码以及与其链接的其他库中明确包含或排除对这些函数的调用。
最后,将实现您实际任务的代码与用于调试它的代码分开几乎总是比较可取的。一种示例方法是为malloc()
编写自己的,有工具的包装,并将其放入一个共享对象中,您可以在该共享对象中插入可执行文件,并且可能介于libc
之间。
答案 1 :(得分:1)
pid提供程序使用类似于调试器断点的机制。 Dtrace会像调试器那样附加到进程。它会根据您的情况查找malloc函数的第一条指令的地址,并在入口点插入陷阱指令。每当调用malloc时,trap指令就会触发控制权转移到dtrace进程,该进程将第一个参数的值保存在其数据结构中的malloc中以供以后聚合,并根据ABI查找该参数的值,最有可能的是受控过程状态的寄存器。 Dtrace恢复在malloc条目处被陷阱指令替换的指令的原始操作码,使受控进程(您的应用程序)单步执行该指令,再次将其替换为陷阱,然后让受控进程继续运行。 / p>
关于您的后续问题“如何以编程方式进行此操作”。这与dtrace无关,但是您可以查看针对C和C ++的BDW垃圾收集器,并将其用作泄漏检测器,或者仅用作收集有关应用程序执行的内存分配信息的方法http://www.hboehm.info/gc/leak.html。最终,您可以在代码中实现类似且简化的方法,但是与使用现有库相比,这可能变得更加乏味和复杂。