Linux----使用GDB调试多进程和多线程程序
来源:互联网 发布:中文域名转码 源码 编辑:程序博客网 时间:2024/05/16 19:51
一、GDB的介绍
1、简介:
GDB(GNU Debugger)是GCC的调试工具,其功能强大,主要帮你完成以下4个方面的功能:
(1).启动你的程序,可以按照你的自定义的要求随心所欲的运行程序。
(2).可让被调试的程序在你所指定的调置的断点处停住。(断点可以是条件表达式)
(3).当程序被停住时,可以检查此时你的程序中所发生的事。
(4).动态的改变你程序的执行环境。
2、gdb(Linux调试器)使用
(1).产生调试信息:要进行代码的调试,就需要有调试信息,要产生调试信息,就需要在源代码生成时添加-g选项;
(2).调试的开始和退出
开始调试:gdb file(file表示要进行调试的源文件)
退出调试:ctrl+d或quit
(3).调试的一些基本操作:
(4).附录;
在gdb中,经常用到的恢复程序运行和单步调试的命令有:
continue 继续运行程序直到下一个断点(类似于VS里的F5)
next 逐过程步进,不会进入子函数(类似VS里的F10)
setp 逐语句步进,会进入子函数(类似VS里的F11)
until 运行至当前语句块结束
finish 运行至函数结束并跳出,并打印函数的返回值(类似VS的Shift+F11)
二、GDB调试多进程
gdb进行多进程调试主要有两种种方法:
分别是:follow-fork-mode 方法和attach 子进程方法。
attach子进程方法:灵活强大,但需要添加额外代码,适合于各种复杂情况,特别是守护进程;
follow-fork-mode方法:方便易用,对系统内核和GDB版本有限制,适合于较为简单的多进程系。
下面重点介绍attach 子进程方法。
1、follow-fork-mode 方法:
在程序fork之前输入
(gdb)set follow-fork-mode [parent|child]
follow-fork-mode的用法为:
(gdb) set follow-fork-mode [parent|child]
parent: fork之后继续调试父进程,子进程不受影响。
child: fork之后调试子进程,父进程不受影响。
因此如果需要调试子进程,在启动gdb后:
(gdb) set follow-fork-mode child
并在子进程代码设置断点。
detach-on-fork参数,指示GDB在fork之后是否断开(detach)某个进程的调试,或者都交由GDB控制:
(gdb) set follow-fork-mode child
on: 断开调试follow-fork-mode指定的进程。
off: gdb将控制父进程和子进程。follow-fork-mode指定的进程将被调试,另一个进程置于暂停(suspended)状态
2、attach 子进程方法:
attach是GDB中中有附着到正在运行的进程中的功能实现,通过attach(pid),就可直接该进程进行调试。 在介绍这种调试方法时,我们需要先对守护进程做一个简单的学习,因为attach方法对于守护进程的调试有很大的作用。
守护进程:
定义:守护进程(daemon)是一类在后台运行的特殊进程,用于执行特定的系统任务。很多守护进程在系统引导的时候启动,并且一直运行直到系统关闭。另一些只在需要的时候才启动,完成任务后就自动结束。
简介:守护进程是一个在后台运行并且不受任何终端控制的进程,如果你了解过信号方面的知识,你就会明白信号在捕捉的时候为什么会单独留下一个‘9号’进程不能被捕获,两者其实都是从保护系统的角度所设计出来的。
守护进程创建步骤:
(1). 创建子进程,父进程退出。
(2).在子进程中创建新对话。
(3).改变当前目录为根目录。
(4).重设文件权限掩码。
(5).关闭文件描述符。
(6).守护进程退出处理。
演示代码:
简单测试(在这段代码中我们很明显会发现父进程中调用的Div函数中有一个除0错误):
#include<stdio.h> #include<pthread.h> #include<stdlib.h> int Div(int num1, int num2) { pit_t id=getpid(); printf("my pid is %d\n",id); int result, diff; diff = num1 - num2; result = num1 / diff; return result; } int main() { pid_t pid; pid = fork(); if (pid <0) { printf("fork err\n"); exit(-1); } else if (pid == 0) {//child int val1 = 5; int val2 = 1; int ret = 0; int i=5; while(i--) {//parent ret = Div(val1, val2); val2++; val1--; printf("cur result is %d\n",ret); } } else {//child sleep(4); wait(-1); exit(0); } }
运行结果:
先让程序运行到后台:执行gdb &
调试结果:
三、GDB调试多线程
gdb提供的多线程调试工具:
新线程创建自动提醒 thread thread-id实现不同线程之间的切换 info threads查询存在的线程 thread apply [thread-id-list] [all] args在一系列线程上执行命令 线程中设置指定的断点 set print thread-events控制打印线程启动或结束是的信息set scheduler-locking off|on|step在使用step或是continue进行调试的时候,其他可能也会并行的执行,如何才能够只让被调试的线程执行呢?该命令工具可以达到这个效果。
off:不锁定任何线程,也就是所有的线程都执行,这是默认值。
on:只有当前被调试的线程能够执行。
step:阻止其他线程在当前线程单步调试时,抢占当前线程。只有当next、continue、util以及finish的时候,其他线程才会获得重新运行的机会。
示例代码:
#include <stdio.h>#include <pthread.h> void* threadPrintHello(void* arg){ while(1) { sleep(5); printf("Hello"); }} void* threadPrintWorld(void* arg){ while(1) { sleep(5); printf("World"); }} int main( int argc , char* argv[]){ pthread_t pid_hello , pid_world; int ret = 0; ret = pthread_create(&pid_hello , NULL , threadPrintHello , NULL); if( ret != 0 ) { printf("Create threadHello error"); return -1; } ret = pthread_create(&pid_world , NULL , threadPrintWorld , NULL); if( ret != 0 ) { printf("Create threadWorld error"); return -1; } while(1) { sleep(10); printf("In main thread"); } pthread_join(pid_hello , NULL); pthread_join(pid_world , NULL); return 0;}
gdb hello 进入调试:
需要调试的地方打下断点,run运行到断点处。如:在 break 10 处打断点,并且 (gdb) r 得:
产生新线程提醒:(1)LWP 3445;(2)LWP 3446 。
查询已经存在的线程:执行(gdb)info threads
主要包括gdb分配的线程id号(例如1,2,3),操作系统分配的线程id(例如20568),线程的名字以及线程相关的调用栈信息。
切换线程
thread threadno可以切换到指定的线程,threadno就是上面gdb分配的线程id号。如threadno = 2:锁定一个线程
默认情况下gdb不锁定任何线程。当我们切换到线程2的时候,使用next执行的时候,发现打印的结果中包含有其他线程的打印信息。可以使用set scheduler-locking on来锁定只有当前的线程能够执行。可以发现锁定线程之后,使用next执行变不会有其它线程的打印结果。执行命令
使用thread apply all bt 来让一个或是多个线程执行指定的命令。例如让所有的线程打印调用栈信息。
后面的命令就不一一实现了,大家照着命令提示做就行了,很简单的!!!!!!
- Linux----使用GDB调试多进程和多线程程序
- Linux下使用gdb调试多进程与多线程程序
- 【Linux】使用gdb调试多进程多线程程序
- Linux:如何使用gdb调试多进程多线程程序
- 使用gdb调试多进程和多线程程序
- 使用gdb调试多进程多线程程序
- 使用gdb调试多进程多线程程序
- 使用gdb调试多进程多线程程序
- 使用gdb调试多进程多线程程序
- 使用GDB调试多进程/多线程程序
- 使用gdb调试多进程多线程程序
- 使用gdb调试多进程、多线程程序
- 使用gdb调试多线程多进程程序
- gdb调试多进程和多线程程序
- 【Linux】使用gdb调试多进程&多线程
- 使用gdb调试多进程和多线程
- 使用gdb调试多进程和多线程
- Linux中gdb程序调试器的命令使用(包括后台进程和多线程的调试)
- Activity启动模式
- 深入了解Java虚拟机中字段表集合,和在class中如何组织
- C\C++应用程序性能优化
- [Spark]Spark RDD 指南四 RDD操作
- SDUVJ开发实录(八):总结
- Linux----使用GDB调试多进程和多线程程序
- Windows平台下python2和3的兼容问题解决
- 进程 线程 协程 管程 纤程 概念对比理解
- 自我对Map的使用方法总结与归纳!
- 背景建模/背景减除/前景提取之背景建模库
- 【Trie+vector】BZOJ4896(Thu Summer Camp2016)[补退选]题解
- caffe添加PrecisionRecallLosslayer层(一)
- Flex中使用DataGrid
- Python基础-字符串格式化_百分号方式_format方式