linux基礎之gdb調試多進程,多線程

一.gdb常用目錄表

操作 描述
l 命令相當於list,從第一行開始列出源碼
回車 重複上一次命令
break +行號 設置斷點
break+函數名 在函數的入口點設置斷點
r 運行程序running的簡寫
into break 查看斷點信息
n 單語句執行 ,next的簡寫
c 繼續運行程序,continue的簡寫
bt 查看函數的堆棧
finish 退出函數
q 退出gdb

二.多進程調試

測試代碼:

#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>


int main()
{
    pid_t id = fork();
    if(id == 0)//child
    {
        printf("I am child ,my id is:%d;my father id is:%d \n",getpid(),getppid());
    }
    else if(id > 0)//parent
    {
        sleep(2);
        printf("I am father:%d \n",getpid());
    }
    else
    {
        perror("fork error");
        return -1;
    }
    return 0;
}

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

parent on 只調試主進程(此程序中系統默認只調試parent)
child on 只調試子進程
parent off 同時調試兩個進程,gdb跟主進程。子進程block(阻塞)在fork位置
child off 同時調試兩個進程,gdb跟子進程,主進程block在fork位置

設置方法如下圖:show follow-fork-mode show detach-on-fork
這裏寫圖片描述

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

這裏寫圖片描述

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

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

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

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

三.多線程調試

多線程代碼

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

void* start_routine1()
{
    printf("I am a thread1 ,my tid is:%u\n",pthread_self());
    return NULL;
}
void* start_routine2()
{
    printf("I am a thread1 ,my tid is:%u\n",pthread_self());
    return NULL;
}
int main()
{
    pthread_t tid1;
    pthread_t tid2;
    pthread_create(&tid1,NULL, start_routine1, NULL);
    pthread_create(&tid2,NULL, start_routine2, NULL);

    pthread_join(tid1,NULL);
    pthread_join(tid2,NULL);
    return 0;
}

注意:在創建線程時候,在編譯鏈接的時候一定要加-lpthread!!!一定要加-lpthread!!!一定要加-lpthread!!!! 重要的事情說三遍,慘痛的教訓
運行圖
這裏寫圖片描述

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

操作 描述
info threads 顯示當前可調試的所有線程,每個線程會有一個GDB爲其分配的ID,後面操作線程的時候會用到這個ID。 前面有*的是當前調試的線程。
thread ID 切換當前調試的線程爲指定ID的線程
break FileName.cpp:LinuNum thread all 所有線程都在文件FileName.cpp的第LineNum行有斷點
thread apply ID1 ID2 command 讓一個或者多個線程執行GDB命令command
thread apply all command 讓所有被調試線程執行GDB命令command
set scheduler-locking off/on/step 在調式某一個線程時,其他線程是否執行。off,不鎖定任何線程,默認值。on,鎖定其他線程,只有當前線程執行。step,在step(單步)時,只有被調試線程運行。
set non-stop on/off 當調式一個線程時,其他線程是否運行
set pagination on/off 在使用backtrace時,在分頁時是否停止
set target-async on/ff 同步和異步。同步,gdb在輸出提示符之前等待程序報告一些線程已經終止的信息。而異步的則是直接返回

四.關於core

core的意思是核心,dumped的意思就是拋出,轉儲,core dumped就是核心轉儲的意思。當一個進程異常退出前,該進程會拋出當時該程序進程的內存詳細情況存儲在硬盤上,文件名通常是core,這就叫core dump。

進程異常終止通常是因爲代碼存在BUG,比如非法內存訪問導致段錯誤,事後可以用調試器檢查core文件以查清錯誤原因,這叫做事後調試.

關於core的指令:

指令 描述
uname -a 查看機器參數
ulimit -a 查看默認參數
ulimit -c 1024 設置core文件大小爲1024
ulimit -c unlimit 設置core文件大小爲無限

修改ulimit的設置,讓它產生。

指令 描述
ulimit -c 1024 設置core文件大小爲1024。要是core文件大於1024個塊,就產生不出來了。
ulimit -c unlimit 設置core文件大小爲無限
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章