【linux】几种进程监控工具

gdb

简述

  • gdb是gcc的调试工具,它主要由c和c++编写的应用程序
  • 功能十分强大
    • 启动程序,可按用户自定义要求随心所欲运行程序
    • 可以让被调试的程序在指定端点停住
    • 当程序被停住时,可以检查此时程序中运行状态
    • 动态的改变程序的运行环境
  • 要调试C/C++程序,需要在编译时将调试信息加入到可执行文件中,使用编译器的-g参数可完成
  • 启动gdb的方法
    • gdb program
      • program是执行文件,一般在当前目录下
    • gdb program core
      • 用gdb同时调试一个运行程序和core文件,core是程序非法执行后core dump后产生的文件
    • gdb program 1234
      • 如果程序是一个服务程序,那么可以指定这个服务程序运行时的进程ID,gdb会自动进行attach操作,并调试这个程序

常见用法

  • 示例代码
//test.cpp
#include<iostream>
using namespace std;
 
int fun(int n)
{
    int res = 0;
    for(int i=1;i<=n;i++)
        res+=i;
    return res;
}
 
int main()
{
    int arr[10];
    arr[0]=0;
    arr[1]=1;
    for(int i=2;i<10;i++)
    {
        arr[i]=arr[i-1]+arr[i-2];
    }
    cout<<"arr[9]"<<arr[9]<<endl;
    cout<<"fun(9)"<<fun(9)<<endl;
    return 0;
}
  • 使用如下命令进行编译程序
g++ -g -o test test.cpp
  • 使用gdb调试程序
gdb test
  • 参数使用帮助
    • l,列出函数代码及其行数
    • b 16,在代码16处设置断点
    • b fun,在函数fun处设置断点
    • info break,查看断点信息
    • r,运行程序
    • n,单条执行语句
    • p i,打印i变量的值
    • bt,查看函数的堆栈
    • finish,退出函数
    • q,结束调试
  • 使用gdb分析coredump文件

    • core又称为coredump文件,是Unix/Linux操作系统的一种机制,对于线上服务来说,出core的过程意味着服务暂时不能响应,需要恢复,并且随着Core进程的内存空间越大,此过程可能持续很长一段时间
    • 凡事皆有两面性,操作系统在coredump时,虽然会终止当前进程,但是也会保留下第一手的现场数据,操作系统仿佛是一架按下快门的相机,照片就是生成的coredump
    • coredump文件包含当进程被终止时内存、CPU寄存器和各种函数调用堆栈信息等,以供后序开发人员调试
    • coredump存储路径
      • 执行命令可以看到core文件存在位置
    • coredump产生条件
    • coredump产生原因
  • gdb定位coredump文件

    • 示例代码
    • 使用命令编译代码并执行

strace

strace是一种调试工具,可以用来跟踪程序系统调用,在Ubuntu下可以通过命令apt install strace安装

  • 也可以用来跟踪信号调用,且可统计系统调用。

示例

实例程序:

#include<iostream>
using namespace std;
int main()
{
    cout<<"Hello World!"<<endl;
    return 0;
}

使用如下命令追踪系统调用

g++ test.cpp -o teststrace ./test

运行结果图

结果分析

  • 每一行都是一次系统调用,等号左边是系统调用的函数名和参数,右边是该调用的返回值
  • 从上面结果图,系统首先调用execve,创建一个新的进程,接着是一些环境初始化,然后在最后倒数第4行,调用write函数将字符串输出到屏幕,最后调用exit_group退出进程

使用strace做信号追踪

  • strace在运行程序时,如果程序被传递了任何信号是可以监视到的
  • 统计系统调用
    • 通过使用 -c 参数,可以将进程的所有系统调用做一个统计分析并显示

SystemTap

SystemTap基于kprobe的实现,可监控内核和用户程序。

示例:

监控运行中程序指定函数的调用参数值。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>

void print(char *p){
    printf("%s.\n", p);
}

void* test_fn(void* arg){
    while(1){
        print("hello");
        sleep(5);
    }
    return ((void *)0);
}

int main(int argc, char **argv){
    pthread+t id;
    int ret;
    ret = pthread_create(&id, NULL, test_fn, NULL);
    if(ret != 0){
        printf("create! \n");
        exit(1);
    }
    printf("int main process.\n");
    pthread_join(id, NULL);
    return 0;
}

以上程序没5秒会调用一次print,我想知道print的输入参数是什么,那么编写SystemTap脚本:

function myprint: string (val)
%{
    char *str = (char *) STAP_ARG_val;
    snprintf(STAP_RETVALUE, MAXSTRINGLEN, "%s", str);
%}
probe process(3266).function("print") {printf("%s\n", myprint($p));}

stap -g test.stp

这样就可以获得监控的结果了,因为用到了内嵌C来获取字符串的值,所以就需要加上-g参数。

DTrace

Dtrace可以监控用户态的程序。