線程的查看以及利用gdb調試多線程


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: %lu\n",pthread_self());
        sleep(1);
    }
}

void* pthread_run2(void* arg)
{
    (void)arg;

    while(1)
    {
        printf("I am thread2,ID: %lu\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 main
//查看當前運行的輕量級進程
 ps -aL | grep -w main
//查看主線程和新線程的關系
pstree -p 主線程id

//查看主線程和新線程的詳細關系

pstree -p user | grep main
|-gnome-terminal-(4573)-+-bash(4583)---main(7991)-+-{main}(7992)
|                                          | `-{main}(7993)

附加:

顯示當前所有進程的進程號和進程id:

pstree -p

顯示所有進程的所有詳細信息,遇到相同的進程名可以壓縮顯示:

pstree  -a

2. 線程棧結構的查看

2.1 安裝pstack

sudo apt-get install pstack

2.2 顯示線程堆棧信息

$ ps -ef | grep main
heah   8199 4583 0 08:51 pts/0 00:00:00 ./main

$ sudo pstack 8199

8199: ./main
pstack: Input/output error
failed to read target.

安裝的pstack有問題,自實現:

#!/bin/sh

if test $# -ne 1; then
    echo "Usage: `basename $0 .sh` <process-id>" 1>&2
    exit 1
fi

if test ! -r /proc/$1; then
    echo "Process $1 not found." 1>&2
    exit 1
fi

# GDB doesn't allow "thread apply all bt" when the process isn't
# threaded; need to peek at the process to determine if that or the
# simpler "bt" should be used.

backtrace="bt"
if test -d /proc/$1/task ; then
    # Newer kernel; has a task/ directory.
    if test `/bin/ls /proc/$1/task | /usr/bin/wc -l` -gt 1 2>/dev/null ; then
    backtrace="thread apply all bt"
    fi
elif test -f /proc/$1/maps ; then
    # Older kernel; go by it loading libpthread.
    if /bin/grep -e libpthread /proc/$1/maps > /dev/null 2>&1 ; then
    backtrace="thread apply all bt"
    fi
fi

GDB=${GDB:-/usr/bin/gdb}

if $GDB -nx --quiet --batch --readnever > /dev/null 2>&1; then
    readnever=--readnever
else
    readnever=
fi

# Run GDB, strip out unwanted noise.
$GDB --quiet $readnever -nx /proc/$1/exe $1 <<EOF 2>&1 | 
set width 0
set height 0
set pagination no
$backtrace
EOF
/bin/sed -n \
    -e 's/^\((gdb) \)*//' \
    -e '/^#/p' \
    -e '/^Thread/p'
#end

 

$ sudo mv mystack /usr/bin/pstack

$ sudo pstack 8199

3. 利用gdb查看線程信息

將進程附加到gdb調試器當中,查看是否創建了新線程:gdb attach 主線程ID

$sudo gdb attach 8199

  1. 查看線程的一些信息

//1.查看進程:info inferiors //2.查看線程:info threads //3.查看線程棧結構:bt //4.切換線程:thread n(n代表第幾個線程)

4. 利用gdb調試多線程

  當程序沒有啟動,線程還沒有執行,此時利用gdb調試多線程和調試普通程序一樣,通過設置斷點,運行,查看信息等等,在這里不在演示,最后會加上調試線程的命令

總結調試多線程的命令

命令

命令 用法
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的行為)以外,只有當前線程會執行

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM