gdb調試多進程與多線程

一,gdb的基礎知識
1>介紹: gdb是Linux環境下的代碼調試工具。 
2>使用:需要在源代碼生成的時候加上 -g 選項. 
3>開始使用: gdb binFile 
4>退出:ctrl + d 或 quit 
5>調試過程中的常用命令:

   list/l 行號:顯示binFile源代碼,接着上次的位置往下列,每次列10行。
   list/l 函數名:列出某個函數的源代碼。
   r或run:運行程序。
   s或step:進入函數調用
   breaktrace(bt):查看各級函數調用及參數
   info(i) locals:查看當前棧幀局部變量的值
   info break :查看斷點信息。
   finish:執行到當前函數返回,然後挺下來等待命令
   print(p):打印表達式的值,通過表達式可以修改變量的值或者調用函數
   set var:修改變量的值
   quit:退出gdb
   break(b) 行號:在某一行設置斷點
   break 函數名:在某個函數開頭設置斷點
   continue(或c):從當前位置開始連續而非單步執行程序
   run(或r):從開始連續而非單步執行程序
   delete breakpoints:刪除所有斷點
   delete breakpoints n:刪除序號爲n的斷點
   disable breakpoints:禁用斷點
   enable breakpoints:啓用斷點
   info(或i) breakpoints:參看當前設置了哪些斷點
   display 變量名:跟蹤查看一個變量,每次停下來都顯示它的值
   undisplay:取消對先前設置的那些變量的跟蹤
   until X行號:跳至X行
   p 變量:打印變量值
   n 或 next:單條執行

二,使用gdb調試多進程

1 ,調試代碼

/**************************************
*文件說明:process.c
****************************************/
#include<stdio.h>
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>

int main()
{
    pid_t pid = fork();//創建子進程

    if(pid == -1)
    {
        perror("fork error");
        return -1;
    }
    else if(pid == 0)//child
    {
        printf("i am a child:my pid is %d,my father is %d\n",getpid(),getppid());
    }
    else//father
    {
        printf("i am a father:my pid is %d\n",getpid());
        wait(NULL);//等待子進程
    }

    return 0;
}

2,默認設置下,在調試多進程程序時GDB只會調試主進程。但是GDB(>V7.0)支持多進程的分別以及同時調試,換句話說,GDB可以同時調試多個程序。只需要設置follow-fork-mode(默認值:parent)和detach-on-fork(默認值:on)即可。

follow-fork-mode detach-on-fork 說明:

parent                   on               只調試主進程(GDB默認)
child                    on               只調試子進程
parent                   off              同時調試兩個進程,gdb跟主進程,子進程block在fork位置
child                    off              同時調試兩個進程,gdb跟子進程,主進程block在fork位置
編譯(需要加上-g選項):

gcc -o process prcess.c -g

1>進入gdb調試模式: 

2>查看系統默認的follow-fork-mode 和 detach-on-fork:

show follow-fork-mode
show detach-on-fork

3>設置follow-fork-mode 和 detach-on-fork:

set follow-fork-mode [parent|child]   
set detach-on-fork [on|off]
  • 這裏寫圖片描述

 

4>用l/list命令查看源代碼(按enter翻頁),分別在子進程和父進程相應位置下斷點: 

下斷點: 


5>運行程序,查詢正在調試的進程: 
顯示GDB調試的所有inferior,GDB會爲他們分配ID。其中帶有*的進程是正在調試的inferior。( GDB將每一個被調試程序的執行狀態記錄在一個名爲inferior的結構中。一般情況下一個inferior對應一個進程,每個不同的inferior有不同的地址空間。inferior有時候會在進程沒有啓動的時候就存在。
 

run
info inferiors


6> 切換調試的進程:

 inferior <infer number>


7>其他

(1)add-inferior [-copies n] [-exec executable]
添加新的調試進程,可以用file executable來分配給inferior可執行文件。增加n個inferior並執行程序爲executable。如果不指定n只增加一個inferior。如果不指定executable,則執行程序留空,增加後可使用file命令重新指定執行程序。這時候創建的inferior其關聯的進程並沒啓動。

(2)remove-inferiors infno
刪除一個infno號的inferior。如果inferior正在運行,則不能刪除,所以刪除前需要先kill或者detach這個inferior。

(3)clone-inferior [-copies n] [infno]
複製n個編號是infno的inferior。如果不指定n的話,就只複製一個inferior。如果不指定infno,則就複製正在調試的inferior。

 (4)detach inferior
detach掉編號是infno的inferior。注意這個inferior還存在,可以再次用run命令執行它。

(5)kill inferior infno: 
kill掉infno號inferior。注意這個inferior仍然存在,可以再次用run等命令執行它。

(6)set schedule-multiple on|off
設爲off:只有當前inferior會執行。 
設爲on:全部是執行狀態的inferior都會執行。 
這個選項類似於多線程調試裏的set .

(7)scheduler-locking
注意:如果scheduler-locking是指爲on,即使schedule-multiple設置爲on,也只有當前進程的當前線程會執行。 
show schedule-multiple: 查看schedule-multiple的狀態。

(8)set follow-exec-mode new|same
設置same:當發生exec的時候,在執行exec的inferior上控制子進程。 
設置爲new:新建一個inferior給執行起來的子進程。而父進程的inferior仍然保留,當前保留的inferior的程序狀態是沒有執行。

show follow-exec-mode
查看follow-exec-mode設置的模式。

(9)set print inferior-events on|off
用來打開和關閉inferior狀態的提示信息。

show print inferior-events
查看print inferior-events設置的狀態。

(10)maint info program-spaces
用來顯示當前GDB一共管理了多少地址空間。

三,gdb 調試多線程
1,多線程程序舉例

 

/**************************************
*文件說明:thread.c
*
*
*開發環境:Ubuntu
****************************************/

#include<stdio.h>
#include<pthread.h>

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

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

int main()
{
    pthread_t tid1,tid2;
    pthread_create(&tid1,NULL,thread1,NULL);//創建線程1
    pthread_create(&tid2,NULL,thread2,NULL);//創建線程2

    pthread_join(tid1,NULL);//等待線程1
    pthread_join(tid2,NULL);//等待線程2 

    return 0;
}



以上代碼中,主線程main創建了兩個子線程分別是thread1和thread2,所以線程的總數爲3個。

2,使用gdb對多線程程序進行調試 
在多線程編程時,當我們需要調試時,有時需要控制某些線程停在斷點,有些線程繼續執行。有時需要控制線程的運行順序。有時需要中斷某個線程,切換到其他線程。這些都可以通過gdb實現。 
GDB默認支持調試多線程,跟主線程,子線程block在create thread。

gdb調試多線程常用命令:

(1)info threads
顯示可以調試的所有線程。gdb會爲每個線程分配一個ID(和tid不同),編號一般從1開始。後面的ID是指這個ID。

1>在主線程處打斷點 
 
由於斷點在第25行,線程1和線程2還沒創建,所以可以調試的只有一個主線程。

2>在線程1中打斷點 

斷點設置在線程1中,顯示可以調試的線程有3個,正在運行的爲線程1.

3>在線程2中打斷點 
 
斷點設置在19行(線程2中),由於線程1已經運行完畢,所以可以調試的線程只有兩個,正在運行的爲線程2。

(2)thread ID
切換當前調試的線程爲指定ID的線程。 


(3)其他 
break FileName.cpp:LinuNum thread all: 
所有線程都在文件FileName.cpp的第LineNum行有斷點。

thread apply ID1 ID2 IDN command: 
讓線程編號是ID1,ID2…等等的線程都執行command命令。

thread apply all command:所有線程都執行command命令。

set scheduler-locking off|on|step: 
在調式某一個線程時,其他線程是否執行。在使用step或continue命令調試當前被調試線程的時候,其他線程也是同時執行的,如果我們只想要被調試的線程執行,而其他線程停止等待,那就要鎖定要調試的線程,只讓他運行。

off:不鎖定任何線程,默認值。 
on:鎖定其他線程,只有當前線程執行。

step:在step(單步)時,只有被調試線程運行。

set non-stop on/off: 
當調式一個線程時,其他線程是否運行。

set pagination on/off: 
在使用backtrace時,在分頁時是否停止。

set target-async on/ff: 
同步和異步。同步,gdb在輸出提示符之前等待程序報告一些線程已經終止的信息。而異步的則是直接返回。

show scheduler-locking: 
查看當前鎖定線程的模式

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章