![]() |
1
2
你应该从阅读开始 Showing the stack trace from a running Python application . 你的具体 问题是关于DTrace的ustack()操作的解释,以及 因此,这个答复可能超出了您的需要。这是因为 DTrace的设计原则是显示系统的精确状态。 因此,即使您对您的 程序,DTrace正在揭示其底层实现。 您提供的输出是一个堆栈,这是一种 描述线程在其 处决例如,如果您有代码
当执行在pause()内时,您请求一个堆栈,然后 你 可以 看到类似
您使用的任何工具都将找到当前指令及其 找到“返回地址”之前的封闭函数,即 该函数最终将返回的点;重复这个 过程生成一个堆栈。因此,尽管应该读取堆栈 从上到下作为一系列返回地址,通常是 作为一系列呼叫者从另一个方向读。注意 程序对应方式的微妙之处 指令的汇编意味着第二种解释 有时可能会产生误导。 为了扩展上面的示例,a()、b()和c()可能是 所有人都在同一个图书馆里——可能有 在其他库中具有相同名称的函数。因此 用于为每个函数显示其所指向的对象 属于。因此,上面的堆栈可能会变成
这在某种程度上有助于开发人员识别 程序以特定状态结束:libfoo中的函数c() 它被称为pause()。然而,还有更多的工作要做:如果c()是 看起来像
那么程序正在等待对pause()的哪个调用? 函数a()、b()和c()将是序列 通常会占用的连续区域的指令 记忆力调用其中一个函数只需要 记录完成后返回的位置(即返回 地址),然后跳到与之对应的存储器地址 函数的开始。函数的起始地址和大小为 记录在嵌入对象的“符号表”中;是 通过读取此表,调试器能够找到函数 包含给定位置(如返回地址)的。因此 具体点 在内部 通常以十六进制表示。因此,一个更好的 上面堆栈的版本可能是
此时,开发人员可以在libfoo.so上使用“反汇编程序” 显示c()中的指令;与c()的比较 源代码将允许他透露特定的行 已调用pause()。 在结束对堆栈的描述之前,值得 再观察一次。如果存在足够的“调试” 在libfoo这样的库中,更好的调试器将能够 要进一步显示,请输入源代码文件名和 中每个“帧”的行号而不是十六进制偏移量 堆栈。 现在,回到你问题中的堆栈, libpython(2.7.so.1)是一个函数执行任务的库 执行Python脚本。Python脚本中的函数是 动态转换为可执行指令,所以我的猜测是 碎片
意味着PyEval_EvalFrameEx()是libpython中的功能 调用Python函数(即,编写的 Python),它驻留在地址0x800b33250.A附近的内存中 简单的调试器可以看到这个地址属于libpython,但是 在库的符号表中找不到相应的条目; 没有选择,它只打印“原始”地址。 因此,您需要查看Python脚本,看看它是什么 但不幸的是,没有迹象表明 中的功能 蟒蛇 堆栈的组件。 有几种方法可以继续。首先是找到 libpython的版本(如果存在),带有 "DTrace helper" 这 是一些额外的功能,允许DTrace查看 Python程序本身,除了周围 实施结果是,每个Python框架都是 用Python源代码中的相应点进行注释。 另一个,如果您在Solaris上,则使用pstack(1);这 对Python的本地支持。
还值得指出的是,您的dtrace调用将显示 您看到的所有堆栈,按流行度排序,无论何时 程序“python2.7”进行系统调用。根据你的描述, 这可能不是你想要的。如果你想理解 挂起的行为,那么您可能想从 python2.7进程的单个快照 在 悬挂 . |