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

主要方法


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:clean
clean:
        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


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


//Makefile
Gdb:Gdb.c
        gcc -o $@ $^ -g -lpthread
.PHONY:clean
clean:
        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版本有限制,适合于较为简单的多进程系


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

double_happiness

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值