你如何以编程方式从父级获取subprocess的堆栈跟踪?

假设我在程序中分支了一个subprocess。 在某个时候,我用kill(child, SIGSTOP)暂停subprocess,并想检查栈的内容。 有没有办法以编程方式从父级获取subprocess的堆栈跟踪

我知道ptrace是追踪subprocess并检查其内存/寄存器的标准方式。 我也知道backtrace调用线程提供了这个function。 有没有合并这些function的函数或库? 或者我需要手动走栈与ptrace

Solutions Collecting From Web of "你如何以编程方式从父级获取subprocess的堆栈跟踪?"

回答我自己的问题 – 这是可行的。 你需要libunwindptracelibunwindptrace提供了一个包装器,允许您展开远程目标。 以下是示例代码,运行NPB基准(cg,A类):

 #include <stdio.h> #include <stdlib.h> #include <time.h> #include <unistd.h> #include <wait.h> #include <sys/ptrace.h> #include <libunwind.h> #include <libunwind-x86_64.h> #include <libunwind-ptrace.h> #include <signal.h> #define panic(X) fprintf(stderr, #X "\n"); static unw_addr_space_t as; static struct UPT_info *ui; void do_backtrace(pid_t child) { ui = _UPT_create(child); if (!ui) { panic("_UPT_create failed"); } ptrace(PTRACE_ATTACH, child, 0, 0); struct timespec t = { .tv_sec = 0, t.tv_nsec = 1000000 }; nanosleep(&t, NULL); unw_cursor_t c; int rc = unw_init_remote(&c, as, ui); if (rc != 0) { if (rc == UNW_EINVAL) { panic("unw_init_remote: UNW_EINVAL"); } else if (rc == UNW_EUNSPEC) { panic("unw_init_remote: UNW_EUNSPEC"); } else if (rc == UNW_EBADREG) { panic("unw_init_remote: UNW_EBADREG"); } else { panic("unw_init_remote: UNKNOWN"); } } do { unw_word_t offset, pc; char fname[64]; unw_get_reg(&c, UNW_REG_IP, &pc); fname[0] = '\0'; (void) unw_get_proc_name(&c, fname, sizeof(fname), &offset); printf("\n%p : (%s+0x%x) [%p]\n", (void *)pc, fname, (int) offset, (void *) pc); } while (unw_step(&c) > 0); ptrace(PTRACE_DETACH, child, 0, 0); _UPT_destroy(ui); } int main(int argc __attribute__((unused)), char **argv, char **envp) { as = unw_create_addr_space(&_UPT_accessors, 0); if (!as) { panic("unw_create_addr_space failed"); } pid_t child; child = fork(); if (!child) { execve("/home/#######/#######/my_utilities/child_bt/cg.Ax", argv, envp); return 0; } else { struct timespec t = { .tv_sec = 1, .tv_nsec = 0 }; nanosleep(&t, NULL); do_backtrace(child); int status; waitpid(child, &status, 0); } return 0; } 

而输出:

 #######-######-desktop:~/popcorn/my_utilities/child_bt$ ./child_bt NAS Parallel Benchmarks (NPB3.3-SER) - CG Benchmark Size: 14000 Iterations: 15 Initialization time = 0.422 seconds iteration ||r|| zeta 1 0.26065081214763E-12 19.9997581277040 2 0.25753187736717E-14 17.1140495745506 3 0.25934878907518E-14 17.1296668946143 4 0.25626292684826E-14 17.1302113581193 5 0.25110613524700E-14 17.1302338856353 6 0.25581937582088E-14 17.1302349879482 7 0.25456477041068E-14 17.1302350498916 8 0.24494068328538E-14 17.1302350537510 0x400c85 : (conj_grad_+0x135) [0x400c85] 0x401ec8 : (MAIN__+0x739) [0x401ec8] 0x402b39 : (main+0x1d) [0x402b39] 0x7f8ee80c2ec5 : (__libc_start_main+0xf5) [0x7f8ee80c2ec5] 0x400a89 : (_start+0x29) [0x400a89] 9 0.24885235903729E-14 17.1302350540101 10 0.24771507610856E-14 17.1302350540284 11 0.24928441017003E-14 17.1302350540298 12 0.24443706061229E-14 17.1302350540299 13 0.24709361922612E-14 17.1302350540299 14 0.24381630450112E-14 17.1302350540299 15 0.24296673223448E-14 17.1302350540299 Benchmark completed VERIFICATION SUCCESSFUL Zeta is 0.1713023505403E+02 Error is 0.5122640033228E-13 CG Benchmark Completed. Class = A Size = 14000 Iterations = 15 Time in seconds = 1.01 Mop/s total = 1483.11 Operation type = floating point Verification = SUCCESSFUL Version = 3.3.1 Compile date = 16 Jul 2015 Compile options: F77 = gfortran FLINK = $(F77) F_LIB = (none) F_INC = (none) FFLAGS = -O FLINKFLAGS = -O RAND = randi8 Please send all errors/feedbacks to: NPB Development Team npb@nas.nasa.gov 

我基于libunwind发行版的tests文件夹中的test-ptrace.c文件中的do_backtrace函数以及此博客中的代码。