ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

如何以编程方式从其父级获取子进程的堆栈跟踪?

2019-07-02 19:39:10  阅读:371  来源: 互联网

标签:c-3 linux stack-trace


假设我在我的程序中分叉子进程.在某些时候,我用kill(child,SIGSTOP)暂停子进程,并想检查堆栈的内容.有没有办法以编程方式从其父进程获取子进程的堆栈跟踪?

我知道ptrace是跟踪子进程并检查其内存/寄存器的标准方法.我也知道backtrace为调用线程提供了这个功能.是否有合并这些功能的功能或库?或者我需要使用ptrace手动移动堆栈吗?

解决方法:

回答我自己的问题 – 这是可行的.你需要libunwind和ptrace. libunwind为ptrace提供了一个包装器,允许您展开远程目标.这是示例代码,运行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函数基于libunwind发行版的tests文件夹中的test-ptrace.c文件以及this blog中的代码.

标签:c-3,linux,stack-trace
来源: https://codeday.me/bug/20190702/1359024.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有