DoubleLi

qq: 517712484 wx: ldbgliet

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

多进程调试
我们使用gdb调试程序,gdb的调试默认是调试父进程的,如果要做到对父进程和子进程都做到调试,所以附加了调试子进程的功能。

  1. 设置条件
    如果让gdb可以同时调试多个程序,只需要设置follow-fork-mode(默认:parent)和detach-on-fork(默认:on)就好了。

follow-fork-mode detach-on-fork 操作
parent on 只调试主进程
child on 只调试子进程
parent off 同时调试两个进程,gdb跟进父进程,子进程block在fork处
child off 同时调试两个进程,gdb跟进子进程,父进程block在fork处
注:设置方法:
set follow-fork-mode [parent|child]
set detach-on-fork [on|off]

  1. 启动方法

  2. gbd program

  3. gdb program core

同时调试一个运行程序和core文件

  1. gdb program pid

如果你的程序是一个服务程序,那么你可以指定这个服务程序运行时的进程。

  1. 查询进程
    查询正在调试的进程:info inferiors
    切换调试的进程:inferior
    添加新的调试进程:add-inferior [-copies n] [-exec executable].
  2. 常见命令
    命令 功能
    I 从第一行开始列出源码
    break func 在函数func的入口处设置断点
    break n 在第n行处设置断点
    info break 查看断点信息
    r 运行程序
    n 单步执行
    c 继续运行
    p 打印变量值
    bt 查看函数堆栈
    finish 退出函数
    shell 命令行 执行shell命令行
    set args 指定运行时参数
    show args 查看设置好的参数
    show paths 查看程序运行路径
    clear n 清除第n行断点
    delete n 删除第n个断点
    disable n 暂停第n个断点
    enable n 开启第n个断点
    step 单步调试如果有函数调用,则进入函数
    list 简记为l,列出程序源代码,默认每次显示十行
    list 行号 将显示当前文件以行号为中心的前后10行代码
    list 函数名 将显示函数名所在函数的源代码
    run 简记为r,运行程序,当遇到断点时,程序会在断点处停止运行。
    回车 重复上一条命令
    print a 将显示整数a的值
    print name 将显示字符串name的值
    watch 表达式 设置一个监视点一旦被监视的“表达式”的值改变,gdb将强行终止正在被调试的程序。
    kill 强制终止当前调试程序
    help help命令将显示常用帮助信息
    call 函数 调试函数
    layout 用于分割窗口,可以一边查看代码,一边测试
    quit 简记为q,退出gdb
    set environment varname [=value] 设置环境变量。如:set env USER=hchen;
    show environment [varname] 查看环境变量;
  3. 调试多进程
    以下面程序为例进行调试:

include <stdio.h>

2 #include <unistd.h>
3 #include <stdlib.h>
4
5 void son_fun()
6 {
7
8 pid_t pid=getpid();
9 printf("son:%d\n",pid);
10 }
11 void father_fun()
12 {
13 pid_t pid=getpid();
14 printf("father:%d\n",pid);
15 }
16 int main()
17 {
18 pid_t id=fork();
19 if(id<0)
20 {
21 perror("fork");
22 exit (1);
else if(id==0)
25 {
26 son_fun();
27 }
28 else
29 {
30 father_fun();
31 }
32 return 0;
33 }

其他重要命令

add-inferior [-copies n] [-exec executable]
添加新的调试进程,可以用file executable来分配给inferior可执行文件。增加n个inferior并执行程序为executable。如果不指定n只增加一个inferior。如果不指定executable,则执行程序留空,增加后可使用file命令重新指定执行程序。这时候创建的inferior其关联的进程并没启动。

remove-inferiors infno
删除一个infno号的inferior。如果inferior正在运行,则不能删除,所以删除前需要先kill或者detach这个inferior。

clone-inferior [-copies n] [infno]
复制n个编号是infno的inferior。如果不指定n的话,就只复制一个inferior。如果不指定infno,则就复制正在调试的inferior。

detach inferior infno
detach去掉编号是infno的inferior。注意这个inferior还存在,可以再次用run命令执行它。

kill inferior infno
kill掉infno号inferior。注意这个inferior仍然存在,可以再次用run等命令执行它

多线程调试
gbd默认支持调试多线程,跟踪主线程,子线程断点在create thread。

  1. 常见命令
    info thread: 查看当前进程的线程
    thread ID :切换调试的线程为指定ID的线程。
    break file.c:100 thread all : 在file文件第100行处为所有经过第100行的线程设置断点。

set scheduler-locking off |on|step
在使用step或continue命令调试当前被调试线程的时候,其他线程也同时执行。
如果只让被调试程序执行,我们需要以下命令。

命令 含义
off 不锁定任何线程,也就是所有线程都执行,默认值。
on 只有当前被调试程序执行
step 在单步的时候,出来next过一个函数的情况(设置断点然后continue的行为)。
2. 调试程序
以下面程序为例进行调试:

void* thread1(void* arg)
{
printf("thread1, tid is %lu\n", pthread_self());
return NULL;
}

void* thread2(void* arg)
{
printf("thread2, tid is %lu\n", pthread_self());
return NULL;
}

int main()
{
pthread_t tid1, tid2;
pthread_create(&tid1, NULL, thread1, NULL);
pthread_create(&tid2, NULL, thread2, NULL);

pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
return 0;

}

posted on 2021-05-08 18:08  DoubleLi  阅读(259)  评论(0编辑  收藏  举报