1. 線程的查看
首先創建兩個線程:
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
void* pthread_run1(void* arg)
{
(void)arg;
while(1)
{
printf("I am thread1,ID: %d\n",pthread_self());
sleep(1);
}
}
void* pthread_run2(void* arg)
{
(void)arg;
while(1)
{
printf("I am thread2,ID: %d\n",pthread_self());
sleep(1);
}
}
int main()
{
pthread_t tid1;
pthread_t tid2;
pthread_create(&tid1,NULL,pthread_run1,NULL);
pthread_create(&tid2,NULL,pthread_run2,NULL);
printf("I am main thread\n");
pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
return 0;
}
分析:上面程序中創建了兩個線程,程序執行起來,main函數所在程序爲主線程,在這個主線程中有兩個新線程運行
命令行查看:
//查看當前運行的進程
ps aux|grep a.out
//查看當前運行的輕量級進程
ps -aL|grep a.out
//查看主線程和新線程的關係
pstree -p 主線程id
3. 利用gdb查看線程信息
將進程附加到gdb調試器當中,查看是否創建了新線程:gdb attach 主線程ID
查看線程的一些信息
//1.查看進程:info inferiors
//2.查看線程:info threads
//3.查看線程棧結構:bt
//4.切換線程:thread n(n代表第幾個線程)
- 1
- 2
- 3
- 4
4. 利用gdb調試多線程
當程序沒有啓動,線程還沒有執行,此時利用gdb調試多線程和調試普通程序一樣,通過設置斷點,運行,查看信息等等,在這裏不在演示,最後會加上調試線程的命令
設置斷點
//1. 設置斷點:break 行號/函數名
//2. 查看斷點:info b
- 1
- 2
執行線程2的函數,指行完畢繼續運行到斷點處
1. 繼續使某一線程運行:thread apply 1-n(第幾個線程) n
2. 重新啓動程序運行到斷點處:r
- 1
- 2
只運行當前線程
1. 設置:set scheduler-locking on
2. 運行:n
- 1
- 2
所有線程併發執行
1. 設置:set scheduler-locking off
2. 運行:n
- 1
- 2
總結調試多線程的命令
命令 | 用法 |
---|---|
info threads | 顯示當前可調試的所有線程,每個線程會有一個GDB爲其分配的ID,後面操作線程的時候會用到這個ID。 前面有*的是當前調試的線程 |
thread ID(1,2,3…) | 切換當前調試的線程爲指定ID的線程 |
break thread_test.c:123 thread all(例:在相應函數的位置設置斷點break pthread_run1) | 在所有線程中相應的行上設置斷點 |
thread apply ID1 ID2 command | 讓一個或者多個線程執行GDB命令command |
thread apply all command | 讓所有被調試線程執行GDB命令command |
set scheduler-locking 選項 command | 設置線程是以什麼方式來執行命令 |
set scheduler-locking off | 不鎖定任何線程,也就是所有線程都執行,這是默認值 |
set scheduler-locking on | 只有當前被調試程序會執行 |
set scheduler-locking on step | 在單步的時候,除了next過一個函數的情況(熟悉情況的人可能知道,這其實是一個設置斷點然後continue的行爲)以外,只有當前線程會執行 |