지정 한 프로 세 스 의 호출 스 택 정 보 를 가 져 올 수 있 습 니까?

backtrace () 를 호출 하면 현재 프로 세 스 의 호출 스 택 정 보 를 얻 을 수 있다 는 것 을 알 고 있 습 니 다. 다른 프로 세 스 (당연히 이 프로 세 스 의 pid) 의 호출 스 택 정 보 를 얻 으 려 면 방법 이 있 습 니까?
stackoverflow 에서 누군가가 이 문 제 를 제기 했다. 어떤 네티즌 은 이 프로 세 스에 신 호 를 보 낸 다음 에 이 프로 세 스 가 신호 처리 함수 에서 자신의 호출 창 고 를 가 져 와 서 다시 보 내 는 것 이 라 고 답 했다.우선 이런 방법 이 되 든 안 되 든 간 에 적어도 일반적인 상황 에 적합 하지 않다. 왜냐하면 그것 은 지 정 된 프로 세 스에 서 신호 처 리 를 해 야 하기 때문이다.
gdb 도 구 를 생각해 보면 gdb 는 거의 모든 프로 세 스 에 첨부 할 수 있 습 니 다. 다른 프로 세 스 가 추가 작업 을 하지 않 아 도 현재 호출 스 택 정 보 를 얻 을 수 있 습 니 다. 그래서 제목 문제 로 돌아 가면 지정 한 프로 세 스 의 호출 스 택 정 보 를 얻 을 수 있 습 니 다. 마침 이러한 특정한 도구 pstack 가 있 습 니 다.
1
2
3
4
5
6
7
8
9
10
11
12 [root@localhost ~]# pstack 4468 Thread 2 (Thread 0x4166f940 (LWP 4469)): #0  0x00007fbcaf6e6b99 in pthread_cond_wait@@GLIBC_2.3.2 () #1  0x00007fbcb071e9fb in ?? () from /proc/4468/exe #2  0x00007fbcaf6e24a7 in start_thread () from /lib64/libpthread.so.0 #3  0x00007fbcaf9cac2d in clone () from /lib64/libc.so.6 Thread 1 (Thread 0x7fbcb06f46e0 (LWP 4468)): #0  0x00007fbcaf9cb018 in epoll_wait () from /lib64/libc.so.6 #1  0x00007fbcb072800c in ?? () from /proc/4468/exe #2  0x00007fbcb0726fec in ?? () from /proc/4468/exe #3  0x00007fbcb071d319 in main () from /proc/4468/exe [root@localhost ~]#
위의 인 스 턴 스 를 통 해 알 수 있 듯 이 pstack 는 지정 한 프로 세 스 (프로 세 스 id 를 통 해) 의 모든 스 레 드 에서 스 택 정 보 를 호출 할 수 있 습 니 다. 어떻게 하 시 겠 습 니까?사실 pstack 은 gdb 를 이용 한 셸 스 크 립 트 입 니 다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52 [root@localhost ~]# ls -l `which pstack` lrwxrwxrwx 1 root root 6 Jul 14  2010 /usr/bin/pstack -> gstack [root@localhost ~]# file /usr/bin/gstack /usr/bin/gstack: Bourne shell script text executable [root@localhost ~]# cat !$ cat /usr/bin/gstack #!/bin/sh
  if test $# -ne 1; then      echo "Usage: `basename $0 .sh` <process-id>" 1>&2      exit 1 fi
  if test ! -r /proc/$1; then      echo "Process $1 not found." 1>&2      exit 1 fi
  # GDB doesn't allow "thread apply all bt" when the process isn't # threaded; need to peek at the process to determine if that or the # simpler "bt" should be used.
  backtrace= "bt" if test -d /proc/$1/task ; then      # Newer kernel; has a task/ directory.      if test `/bin/ls /proc/$1/task | /usr/bin/wc -l` -gt 1 2>/dev/null ; then      backtrace= "thread apply all bt"      fi elif test -f /proc/$1/maps ; then      # Older kernel; go by it loading libpthread.      if /bin/grep -e libpthread /proc/$1/maps > /dev/null 2>&1 ; then      backtrace= "thread apply all bt"      fi fi
  GDB=${GDB:-/usr/bin/gdb}
  if $GDB -nx --quiet --batch --readnever > /dev/null 2>&1; then      readnever=--readnever else      readnever= fi
  # Run GDB, strip out unwanted noise. $GDB --quiet $readnever -nx /proc/$1/exe $1 <<EOF 2>&1 | $backtrace EOF /bin/sed -n \      -e 's/^(gdb) //' \      -e '/^#/p' \      -e '/^Thread/p' [root@localhost ~]#

좋은 웹페이지 즐겨찾기