gpt4 book ai didi

c - 您如何以编程方式从父进程获取子进程的堆栈跟踪?

转载 作者:IT王子 更新时间:2023-10-29 00:34:19 26 4
gpt4 key购买 nike

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

我知道 ptrace 是跟踪子进程并检查其内存/寄存器的标准方法。我还知道 backtracecalling 线程提供了这个功能。是否有合并这些功能的函数或库?或者我是否需要使用 ptrace 手动遍历堆栈?

最佳答案

回答我自己的问题 - 这是可行的。您需要 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.A.x",
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

我将 do_backtrace 函数基于 libunwindtests 文件夹中的 test-ptrace.c 文件> 分发,以及来自 this blog 的代码。

关于c - 您如何以编程方式从父进程获取子进程的堆栈跟踪?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31437045/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com