其實,我們在VS編譯器中用的調試工具是集成的軟件,但是在Linux中有特定的工具GDB,其實這是一個很強的工具,我其實用的不是很6,其實這個真的強,希望大家和我一樣努力的來學習使用GDB調試;在這先推薦一個大神陳皓,博客已經不更新了但是還是有很多內容比如GDB調試
其實在陳皓大神的這個系列中,我們可以get很多的技能;
GDB調試多進程
在GDB調試中,默認的調試是父進程,當我們在程序中fork出一個子進程後,就不能達到調試子進程的目的,因此,GDB中肯定就會設置調試子進程的
set follow-fork-mode child/parent
上述的命令就是在gdb中調試的時候可以選擇gdb調試的是父進程還是子進程;
set follow-fork-mode child //GDB調試子進程
set follow-fork-mode parent //GDB調試父進程
我們先展示一下我們的測試代碼:
//test.c
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
int main()
{
pid_t id = fork();
if(id == 0)//child
{
int a = 0, i;
for(i = 0; i < 5; i++)
{
a += i;
}
}
else
{
int b = 1, j;
for(j = 1; j < 5; ++j)
{
b *= j;
}
}
return 0;
}
在GDB調試之前,我們隊目標文件編譯的時候必須在 編譯後面加 -g才能正確的進入GDB的調試:
在上圖中,我們可以看到我什麼也沒有添加的調試後,直接進入的父進程,跳過了子進程;所以:GDB默認調試的父進程;
結合上圖,我們可以看到的是,在子程序調試完後,直接就到24行退出;
其實在我們這個GDB調試中,父進程也可以用 set follow-fork-mode parent,也可以直接調試,畢竟默認的也是調試父進程;
在GDB調試多進程中還有一個調試的命令: set detach-on-fork on/off;
兩個命令的聯繫如下:
follow-fork-mode | detach-on-fork | 說明 |
---|---|---|
parent | on | GDB默認的調試方式;值調試主進程 |
child | on | 只調試子進程 |
parent | off | 同時調試兩個進程,gdb跟主進程,子進程block在fork位置 |
child | off | 同時調試兩個進程,gdb跟子進程,主進程block在fork位置 |
所以,我們可以用上述命令調試多進程的程序:
我們在看到所有運行的進程後,可以選擇調試那個進程:
GDB調試多線程
//thread.c
#include<stdio.h>
#include<pthread.h>
#include<stdlib.h>
void* thread1(void* arg)
{
while(1)
{
sleep(5);
printf("Hello\n");
}
}
void* thread2(void* arg)
{
while(1)
{
sleep(5);
printf("world\n");
}
}
int main()
{
pthread_t tid1;
pthread_t tid2;
pthread_create(&tid1, NULL, thread1, NULL);
pthread_create(&tid2, NULL, thread2, NULL);
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
return 0;
}
線程創建提醒
在GNU/Linux上,如果gdb檢測一個新的線程,會給出如下通知:
查詢已經創建的線程
線程切換
thread threadno可以切換到指定的線程,threadno就是上面gdb分配的線程id號
鎖定一個線程
默認情況下,gdb不鎖定任何線程:在切換到線程2中後,打印的不只是線程2中的數據,也還有線程3中的內容:
可以使用set scheduler-locking on來鎖定只有當前線程的操作:不會執行其他線程的結果
scheduler-locking | on | off | step |
---|---|---|---|
調試某個線程是其他線程是否執行 | 鎖定其他線程,只有當前線程執行 | 不鎖定任何線程,默認值 | 在單步時,只有被調試線程運行 |
線程調試的其他命令:
thread apply ID command:讓ID線程執行命令command;
thread apply all command:讓所有線程執行命令command;