2010-09-02 73 views
3

我正在开发一个项目,在那里我需要获取Java应用程序的本地堆栈。我能够部分实现这一目标。感谢ptrace/multiprocessing和信号。多线程,带停止和继续信号的多处理

Linux上正常的java应用程序有最少14个线程数。在这14个我感兴趣的只有主线程,我必须得到本地堆栈。考虑到这个目标,我已经开始了一个使用fork()的独立进程,它监视主线程的本地堆栈。总之,我有两个独立的过程:一个正在被监控,另一个正在使用ptrace和信号处理进行监控。

步骤,在监测过程:

1)获得主线程ID了其他14线程从过程。

2)PTRACE_ATTACH main_ID

3)ptrace_cont main_ID

连续循环开始

{

4)杀(main_ID,SIGSTOP)

5 )nanosleep并检查/ proc/[p ID]/STAT DIR

6)ptrace_peekdata读取堆栈和导航

7)ptrace_cont main_ID

8)了nanosleep和从/ proc/[PID]/STAT检查状态DIR

}

9)ptrace_detach main_ID

,这一完全给出了本地栈我信息不断。但有时我遇到了一个问题。

问题:

当我送杀(main_ID,SIGSTOP)到主线程,从过程中其他线程获得成品或采空状态(T)和全过程块。这不是一致性行为,整个过程正确执行。我无法理解这种行为,因为我只是向主线程发出信号,为什么其他线程会受到影响? 有人可以帮我分析问题吗?

我也尝试在进程的所有线程上执行CONT和STOP信号,但问题仍然有时会出现。

感谢,桑迪普

+0

按照我迄今为止的理解。 – 2010-10-26 10:42:40

+0

有一个默认信号处理程序对应于过程级别上的信号。当进程找到其任何子线程的信号时,各个信号正由任何一个线程处理,这取决于状态,即忙或闲。这可能是导致我的结果不一致的原因。 – 2010-10-26 10:48:11

回答

0

假设你使用Linux,你应该使用tkill(2)或tgkill(2)而不是杀死(2)。在FreeBSD上,你应该使用SYS_thr_kill2系统调用。每tkill(2)用户手册:

tgkill()发送信号sig与在 线程组TGID线程ID TID线程。(相比之下,kill(2)只能用于将一个信号作为一个整体发送给一个进程(即线程组),并且信号 将被传递到该进程内的任意线程中。)

忽略关于tkill(2)和朋友正在使用内部线程库的内容,它通常被调试器/跟踪器用来向特定线程发送信号。

此外,您应该使用waitpid(2)(或它的一些变体)等待线程接收SIGSTOP,而不是轮询/ proc/[pid]/stat。这种方法将更加高效和响应更快。

最后,你似乎在做某种堆栈抽样。您可能想要查看Google PerfTools,因为这些工具包含一个正在进行堆栈抽样的CPU采样器,以获取哪些功能消耗最多CPU时间的估计值。您可能可能重复使用这些工具已经完成的工作,因为堆栈抽样可能会非常棘手以提高可靠性。