GDB调试下的多进程与多线程

来源:互联网 发布:淘宝背景材图 编辑:程序博客网 时间:2024/05/18 00:54

主要方法


1、attach方法

2、follow-fork-mode方法


背景知识


首先要进行调试,我们就不得不先搞清楚调试的一些基本操作。


gdb(Linux调试器)使用


(1)产生调试信息:要进行代码的调试,就需要有调试信息,要产生调试信息,就需要在源代码生成时添加-g选项;

(2)调试的开始和退出


开始调试:gdb file(file表示要进行调试的源文件)

退出调试:ctrl+d或quit


(3)调试的一些基本操作




attach调试方法


attach是GDB中中有附着到正在运行的进程中的功能实现,通过attach(pid),就可直接该进程进行调试


在介绍这种调试方法时,我们需要先对守护进程做一个简单的学习,因为attach方法对于守护进程的调试有很大的作用


守护进程


定义:守护进程(daemon)是一类在后台运行的特殊进程,用于执行特定的系统任务。很多守护进程在系统引导的时候启动,并且一直运行直到系统关闭。另一些只在需要的时候才启动,完成任务后就自动结束。


简介:守护进程是一个在后台运行并且不受任何终端控制的进程,如果你了解过信号方面的知识,你就会明白信号在捕捉的时候为什么会单独留下一个‘9号’进程不能被捕获,两者其实都是从保护系统的角度所设计出来的。


守护进程创建步骤:


(1)创建子进程,终结父进程;

(2)在子进程中创建新会话;

(3)改变工作目录;

(4)重建子网掩码;


简单测试(在这段代码中我们很明显会发现父进程中调用的Div函数中有一个除0错误):


//Makefile(Makefile中的注释并不是“//”这里这是为了表示文件的信息,后面将不再做解释)gdb:gdb.c        gcc -o $@ $^ -g -lpthread.PHONY:cleanclean:        rm -f gdb

代码编译结果:


#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 &




调试演示:




follow-fork-mode调试方法


使用方法:


set follow-fork-mode [parent|child]

(1)parent:fork之后继续调试父进程,子进程不受影响

(2)child::fork之后继续调试子进程,父进程不受影响


子进程调试方法:


启动gdb之后:


(gdb) set follow-fork-mode child

(1)在子进程相应可能会出错的地方设置断点

(2)设置detach-on-fork参数(用于指示gdb在fork之后,gdb的进程)

设置方法设置方法:set follow-fork-mode [parent|child]   set detach-on-fork [on|off]

具体设置和功能如图所示:(GDB 6.6或以上版本



常用的一些其他方法:


查询正在调试的进程:info inferiors
切换调试的进程: inferior <infer number>
添加新的调试进程: add-inferior [-copies n] [-exec executable] ,可以用file executable来分配给inferior可执行文件。
其他:remove-inferiors infno, detach inferior


简单演示(这个我们只是走一下调试的过程本身并没有错误):


//MakefileGdb:Gdb.c        gcc -o $@ $^ -g -lpthread.PHONY:cleanclean:        rm -f Gdb

#include<stdio.h>#include<pthread.h>void* Thread(void* arg){        pid_t id=getpid();        printf("I am a thread, my pid is %d\n",id);}void childfunc(){        pid_t id=getpid();        printf("I am a child , my pid is %d\n",id);}void parentfunc(){        pid_t id=getpid();        int stat;        pthread_t pt;        printf("I am a parent , my pid is %d\n",id);        stat=pthread_create(&pt,NULL,Thread,NULL);        if(stat!=0){                printf("parent process can not create thread");        }        Thread(NULL);        sleep(2);}int main(){        int id=fork();        if(id<0){                perror("fork");                return -1;        }        else if(id==0){//child                childfunc();                sleep(2);        }        else{//parent                parentfunc();                sleep(2);        }        return 0;}


运行结果:




调试演示:


(1)调试主进程,block子进程




(2)切换到子进程




(3)调试主进程中产生的两个线程




两种调试方法比较


attach子进程方法灵活强大,但需要添加额外代码,适合于各种复杂情况,特别是守护进程;

follow-fork-mode方法:方便易用,对系统内核和GDB版本有限制,适合于较为简单的多进程系


原创粉丝点击