使用gdb调试多进程多线程程序

使用gdb调试多进程多线程程序 高能预警 本文主要介绍了如何使用linux环境下的代码调试工具—gdb调试多进程多线程程序,主要内容有: 1. 问题引入 2. 调试方法介绍及代码实例 3. gdb常用命令总结 4. 一些大神们关于此主题的介绍并附链接 ——>全篇阅读(不包括链接)大概需要8min 读完本文后,你可以用简单的方法调试多线程多进程程序。对几种调试方法也会有一种宏观认识。 问题引入 先 阅读详情

今天我们来谈谈如何使用gdb调试多进程和多线程程序???       

       其实gdb本身没有对多进程程序调试提供直接支持。例如,使用gdb调试某个进程,如果该进程fork了子进程,gdb会继续调试该进程,子进程会不受干扰地继续运行下去。如果我们事先在子进程代码里设定了断点,子进程会收到SIGTRAP信号并终止。所以我们可以通过去子进程设置断点,再通过step与continue交替运行,找到最终程序错误的“罪魁祸首”。

一、使用gdb调试多进程程序

      我们先来看一段测试代码,在该代码中创建了一个子进程,子进程中有一个除0错误,我们需要用gdb调试来找出这个错误。



调试原理:

       首先要强调的一点是,既然要调试,在Makefile文件里就要加上-g选项,才能支持调试。大家主要看我在创建的子进程的代码中加入了 sleep(60),这就是关键所在。为什么先要让子进程休眠,是因为在子进程休眠过程中,我们需要通过ps aux | grep '文件名'来找到当前运行进程的pid,用于attach pid调试进程使用。

调试过程:

      先来看看我使用gdb调试的整个过程,以及程序的运行结果:





      大家注意看,在我调试的最后一行print b,我打印b的值发现是0,这就找出了问题的关键!我的程序中出现了除0错误。

      我大概把调试过程梳理一遍,我们获取到当前进程的pid后,启动gdb进行调试,使用attach命令关联到当前进程,然后在子进程的代码中设置一个断点,用来调试子进程找出程序错误。然后使用step 与 continue交替使用进行单步执行,在执行其中我们还需要追踪变量的值使用print来判断错误出现在哪个变量中。

二、使用gdb调试多线程程序

大家先来看我写的测试代码,在代码中我总共只创建了两个线程。顺便再来熟悉一下pthread_create创建线程这个函数。






首先要获取到进程的pid后,启动gdb来调试,再使用attach进程号来关联到当前运行的进程。因为进程中创建了两个线程,再加上主线程总共是三个。

info pthreads用来查看当前所有在运行的线程,最前面的编号是gdb分配的线程号;

thread ID 切换当前调试的线程为指定ID的线程,在此程序中就会有三个线程1,2,3可供切换;

break thread_test.c:123 thread all 在所有线程中相应的行上设置断点;

set scheduler-locking off|on|step 我们会发现,在使用step或者continue命令调试当前被调试线程的时候,其他线程也是同时执行的,怎么只让被调试程序执行呢?通过这个命令就可以实现这个需求。off 不锁定任何线程,也就是所有线程都执行,这是默认值。 on 只有当前被调试程序会执行。 step 在单步的时候,除了next过一个函数的情况以外,只有当前线程会执行。

调试过程仅供参考:



在我的调试过程中,我没有使用set scheduler-locking off|on|step 这条指令,所以当我选择的三号线程执行结束时,其他线程也都执行结束后退出了。这是调试程序结果:


三、gdb调试程序指令

gdb program

program 也就是你的执行文件,一般在当前目录下。

gdb program core

用gdb同时调试一个运行程序和core文件,core是程序非法执行后core dump后产生的文件。

gdb program 1234

如果你的程序是一个服务程序,那么你可以指定这个服务程序运行时的进程ID。gdb会自动attach上去,并调试他。program应该在PATH环境变量中搜索得到。

set args 可指定运行时参数。(如:set args 10 20 30 40 50 ) 
show args 命令可以查看设置好的运行参数。 
run (r)     启动程序 
不指定运行参数 r 
指定运行参数    r 10 20 30 40 50

info terminal显示你程序用到的终端的模式。 

使用重定向控制程序输出。如:run > outfile 

tty命令可以设置输入输出使用的终端设备。如:tty /dev/tty1

break      设置断点,可以简写为b 
b 10  设置断点,在源程序第10行 
b func 设置断点,在func函数入口处

info b  查询所有断点

watch                  为表达式(变量)expr设置一个观察点。当表达式值有变化时,马上停住程序。 
rwatch      表达式(变量)expr被读时,停住程序。 
awatch                 表达式(变量)的值被读或被写时,停住程序。 
info watchpoints列出当前所设置了的所有观察点。

维护停止点:

clear清除所有的已定义的停止点;     clear function清除所有设置在函数上的停止点;     clear linenum清除所有设置在指定行上的停止点;     clear filename:linenum清除所有设置在指定文件:指定行上的停止点;     delete [breakpoints] [range...]删除指定的断点,breakpoints为断点号。如果不指定断点号,则表示删除所有的断点;     range表示断点号的范围(如:3-7)。其简写命令为d;     比删除更好的一种方法是disable停止点,disable了的停止点,GDB不会删除,当你还需要时,enable即可,就好像回收站一样;     disable [breakpoints] [range...] disable所指定的停止点,breakpoints为停止点号。如果什么都不指定,表示disable所有的停止点。简写命令是dis.;     enable [breakpoints] [range...]enable所指定的停止点,breakpoints为停止点号;     enable [breakpoints] once range…enable所指定的停止点一次,当程序停止后,该停止点马上被GDB自动disable;     enable [breakpoints] delete range…enable所指定的停止点一次,当程序停止后,该停止点马上被GDB自动删除

调试代码:

run 运行程序,可简写为r        next 单步跟踪,函数调用当作一条简单语句执行,可简写为n       step 单步跟踪,函数调进入被调用函数体内,可简写为s     finish 退出函数       until 在一个循环体内单步跟踪时,这个命令可以运行程序直到退出循环体,可简写为u       continue 继续运行程序,可简写为c     stepisi, nextini 单步跟踪一条机器指令,一条程序代码有可能由数条机器指令完成,stepi和nexti可以单步执行机器指令       info program 来查看程序的是否在运行,进程号,被暂停的原因。

查看运行数据:

print 打印变量、字符串、表达式等的值,可简写为p         p count 打印count的值        p cou1+cou2+cou3 打印表达式值        print接受一个表达式,GDB会根据当前的程序运行的数据来计算这个表达式,表达式可以是当前程序运行中的const常量、变量、函数等内容。但是GDB不能使用程序中定义的宏。

堆栈相关命令:

backtrace/bt  bt  用来打印栈帧指针,也可以在该命令后加上要打印的栈帧指针的个数,查看程序执行到此时,是经过哪些函数呼叫的程序,程序“调用堆栈”是当前函数之前的所有已调用函数的列表(包括当前函数)。每个函数及其变量都被分配了一个“帧”,最近调用的函数在 0 号帧中(“底部”帧);

frame  frame 1  用于打印指定栈帧;       info reg  info reg  查看寄存器使用情况 ;       info stack  info stack  查看堆栈使用情况 ;      up/down  up/down  跳到上一层/下一层函数


信号命令:

signal   signal SIGXXX   产生XXX信号,如SIGINT。一种速查Linux查询信号的方法:# kill -l

handle   在GDB中定义一个信号处理。信号可以以SIG开头或不以SIG开头,可以用定义一个要处理信号的范围(如:SIGIO-SIGKILL,表示处理从SIGIO信号到SIGKILL的信号,其中包括SIGIO,SIGIOT,SIGKILL三个信号),也可以使用关键字all来标明要处理所有的信号。一旦被调试的程序接收到信号,运行程序马上会被GDB停住,以供调试。其可以是以下几种关键字的一个或多个:
nostop/stop当被调试的程序收到信号时,GDB不会停住程序的运行,但会打出消息告诉你收到这种信号/GDB会停住你的程序;  
print/noprint当被调试的程序收到信号时,GDB会显示出一条信息/GDB不会告诉你收到信号的信息; 
pass noignore 当被调试的程序收到信号时,GDB不处理信号。这表示,GDB会把这个信号交给被调试程序会处理;
nopass ignore 当被调试的程序收到信号时,GDB不会让被调试程序来处理这个信号;
info signals info handle 可以查看哪些信号被GDB处理,并且可以看到缺省的处理方式;

single命令和shell的kill命令不同,系统的kill命令发信号给被调试程序时,是由GDB截获的,而single命令所发出一信号则是直接发给被调试程序的。

跳转执行:

jump  指定下一条语句的运行点。可以是文件的行号,可以是file:line格式,可以是+num这种偏移量格式。表式着下一条运行语句从哪里开始。相当于改变了PC寄存器内容,堆栈内容并没有改变,跨函数跳转容易发生错误。








使用gdb调试多进程多线程程序 多进程调试:首先来了解下会可能会用到的调试命令: 1.默认设置下,在调试多进程程序GDB只会调试主进程。 但是如果设置follow-fork-mode的话,就可调试多个进程。 set follow-fork-mode parent|child: 进入gdb后默认调试的是parent,若是想要调试child的话,需要设置set follow-fork-mode child,然后 阅读详情

相关推荐

GDB多线程调试总结

多线程 gdb

renjianhhong的博客 1863

GDB多线程调试调试命令+调试演示)

多线程调试 (一)多线程调试命令 shell的命令: (1)查看当前运行的进程:ps aux | grep book (2)查看当前运行的轻量级进程:ps -aL | grep book (3)查看主线程和子线程的关系:pstree -p 主线程id gdb的命令: (1)查看可切换调试的线程:info threads (2)切换调试的线程:thread 线程id (3)只运行当前线程:set scheduler-locking on (4)运行全部的线程:set schedul..

weixin_42158742的博客 2万+

sysbench安装(在线&离线)

sysbench下载、安装、编译和异常处理方法

m0_61066945的博客 8685

gdb多线程调试

采用gdb调试代码时,经常遇到多线程的情况,但对gdb多线程中的切换并不熟悉,导致排查问题很困难,所以整理下多线程调试方法。如果只想n或者s单步调试锁定线程时:set scheduler-locking step。锁定当前线程,暂停其它线程:set scheduler-locking on,调试代码时先将代码跑起来,然后ctrl+c将代码中断。查看线程信息:i threads [id …注意:打了断点后,执行到断点会暂停所有线程。不指定id就查看所以的线程信息。切换线程:thread id。

HuYingJie_1995的博客 2857

GDB调试进程方法

GDB调试进程方法

weixin_40813576的博客 4170

GDB之(5)线程和进程调试

在操作系统的世界里,尤其是在Linux这一广受欢迎的开源系统中,进程(Process)和线程(Thread)是两种基础且核心的执行单位,它们共同构建起了系统进行任务管理和调度的基石。为了理解二者的联系和区别,可以将进程想象为一个工厂,而线程则是工厂里的工人。进程可以被看作是一个程序的运行实例。它拥有独立的内存空间、数据栈以及其他用于跟踪执行的辅助数据。每个进程至少有一个线程,即主线程,但可以包含更多的线程。在Linux中,创建进程通常通过系统调用fork()

梅花香自苦寒来,宝剑锋从磨砺出。 2264

C语言gdb调试

文章目录一、gdb的安装二、调试前的准备三、基本调试命令四、调试core文件1.修改系统资源限制参数2.core 文件存放的路径3.gdb 调试加上 core 文件五、调试正在运行中的程序1.运行示例程序2.查看进程编号3.gdb 调试加入进程编号六、调试多进程服务程序1.示例程序2.先用 gdb 进去调试3.gdb默认调试父进程4.停止其他的进程5.查看可以调试的进程: info inferiors6.切换调试的进程:inferior + Num七、调试多线程1.测试代码2.运行程序3.查看线程3.1 查

qq_43403759的博客 3884

Linux:如何使用gdb调试多进程多线程程序

1. 默认设置下,在调试多进程程序GDB只会调试主进程。但是GDB(>V7.0)支持多进程的分别以及同时调试,换句话说,GDB可以同时调试多个程序。只需要设置follow-fork-mode(默认值:parent)和detach-on-fork(默认值:on)即可。 follow-fork-mode detach-on-fork 说明parent on 只调试主进程(GDB默认)

peter——wang的博客 714

使用gdb调试多线程多进程程序

GDB的基本介绍 GDB是GUN开源组织发布的一个强大的UNIX下的程序调试工具。或许,平时大家更加习惯图形界面的调试,比如VS上的IDE调试;但是如果我们在UNIX或Linux下做软件,我们呢就更加需要熟练GDB这个调试工具。

One piece 888

Linux----使用GDB调试多进程多线程程序

一、GDB调试多进程

rengui1228的博客 680

使用gdb调试多进程多线程程序

默认设置下,在调试多进程程序GDB只会调试主进程。但是GDB(>V7.0)支持多进程的分别以及同时调试,换句话说,GDB可以同时调试多个程序。只需要设置follow-fork-mode(默认值:parent)和detach-on-fork(默认值:on)即可。    follow-fork-mode detach-on-fork 说明 parent

月已满西楼的博客 662

程序调试利器GDB使用指南

GDB是GNU Debugger的简称,其作用是可以在程序运行时,检测程序正在做些什么。GDB程序自身是使用C和C++程序编写的,但可以支持除C和C++之外很多编程语言的调试GDB原生支持调试的语言包含:•C•C++•D•Go•Object-C•OpenCL C•Fortran•Pascal•Rust•Modula-2•Ada此外,通过扩展GDB,也可以用来调试Python语言。

sunxiaojun 2662

gdb调试进程

调试过程中,你还可以修改变量的值,使用命令`set variable <variable_name> = <new_value>`。- `continue`或`c`:从当前位置继续执行程序,直到遇到下一个断点或程序结束。- `backtrace`或`bt`:显示函数调用的回溯栈,帮助理解程序的执行流程。- `next`或`n`:执行下一行代码,但如果是函数调用,则不会进入函数内部。- `step`或`s`:执行下一行代码,如果遇到函数调用,则会进入函数内部。其中`<pid>`是进程的ID。

weixin_43803780的博客 1399

使用gdb调试多线程的方法

多线程死锁的调试方法: kill -11 得到 coredump 然后分析 在出现死锁时,kill -11 得到 coredump 然后分析 打印日志 把日志写的详细一些,可以反映出程序运行时的真是情况 gdb gdb法有个致命的缺陷,就是它打乱了多线程的真是调度顺序。 多线程特定的错误往往是由于缺乏对共享数据的保护而导致的竞争状态的出现,而竞争状态的出现是具有偶然性的,取决于特定的调度次序;而当设置断点时,实际是将调度器的权限由系统交给调试者。这样在调试环境重现的,可能并不是bug时的真实情况

ArtAndLife的博客 5650

linux工具---gdb调试~~进程

1.gdb的简单介绍 1.1程序发布版本 1.2前期准备 1.3调试开始和结束 1.4调试的相关指令 1.4.1设置断点 1.4.2单步执行 1.4.3运行程序 1.4.4查看变量的数值 1.4.5断点之间跳转 1.4.6查看调试程序的代码 2.进程入门 2.1简单回顾 2.2进程初识 2.3进程属性 2.3linux里面的PCB 2.4查看进程 2.5查看进程的标识符 2.6创建进程

大学成长道路上的探索经历与点滴思考,与君共勉,共筑成长。 1469

本题要求你写个程序把给定的符号打印成沙漏的形状。例如给定17个“*”,要求按下列格式打印

本题要求你写个程序把给定的符号打印成沙漏的形状。例如给定17个“*”,要求按下列格式打印

ProceduralMan的博客 7385

Sanet.st_Prompt Engineering for LLMs - John Berryman.pdf

Sanet.st_Prompt Engineering for LLMs - John Berryman.pdf

上一篇: Linux信号3
下一篇: 作业规划进程crond
SMQsmq
博客等级 码龄10年 4粉丝 41原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值