91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Linux多進程和多線程的一次gdb調試

發布時間:2021-06-24 10:07:44 來源:億速云 閱讀:254 作者:chen 欄目:大數據

本篇內容介紹了“Linux多進程和多線程的一次gdb調試”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

1 原文整理

默認設置下,在調試多進程程序時gdb只會調試主進程。gdb7以上的版本(gdb --version)支持多進程調試,只需要設置好follow-fork-mode(fork追蹤模式)以及detach-on-fork(指示GDB在fork之后是否斷開某個進程的調試)即可。

這兩個參數的設置命令分別是:set follow-fork-mode [parent|child],set detach-on-fork [on|off]。兩者結合起來構成了GDB的調試模式:

follow-fork-mode  detach-on-fork    說明
    parent              on          GDB默認的調試模式:只調試主進程
    child               on          只調試子進程
    parent              off         同時調試兩個進程,gdb跟主進程,子進程block在fork位置
    child               off         同時調試兩個進程,gdb跟子進程,主進程block在fork位置

查看gdb默認的參數設置:

(gdb) show follow-fork-mode
Debugger response to a program call of fork or vfork is "parent".
(gdb) show detach-on-fork
Whether gdb will detach the child of a fork is on.
(gdb)
2 演示代碼

下面這段代碼的主要流程就是在main函數中fork創建一個子進程,然后在父進程中又創建一個線程,接著就使用gdb進行調試(block子進程)。注意,在調試設置斷點的時候,由于之前調試的時候代碼最前面沒有加上這7行說明文字,所以設置斷點的行號要加上7。

1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
/** 
 * @FileName    gdb_pthread.c
 * @Describe    A simple example for the debug of multiprocess and multithreading using gdb in linux system.
 * @Author      vfhky 2016-02-25 22:48 https://typecodes.com/cseries/multilprocessthreadgdb.html
 * @Compile     gcc gdb_pthread.c -g -o gdb_pthread
 * @Reference   http://blog.csdn.net/pbymw8iwm/article/details/7876797
 */
#include <stdio.h>
#include <pthread.h>
#include <sys/types.h>
#include <unistd.h>


//Parent process handle.
void Parent();
//Child process handle.
void Child();
//Parent process handle after generate a thread.
void * ParentDo( char *argv );

int main( int argc, const char **argv )
{
    int pid;
    pid = fork();
    if(pid != 0)        //add the first breakpoint.
        Parent();
    else
        Child();
    return 0;
}

//Parent process handle.
void Parent()
{
    pid_t pid = getpid();
    char cParent[] = "Parent";
    char cThread[] = "Thread";
    pthread_t pt;

    printf( "[%s]: [%d] [%s]\n", cParent, pid, "step1" );

    if( pthread_create( &pt, NULL, (void *)*ParentDo, cThread ) )
    {
        printf( "[%s]: Can not create a thread.\n", cParent );
    }

    ParentDo( cParent );
    sleep(1);
}

void * ParentDo( char *argv )
{
    pid_t pid = getpid();
    pthread_t tid = pthread_self();     //Get the thread-id selfly.
    char tprefix[] = "thread";

    printf( "[%s]: [%d] [%s] [%lu] [%s]\n", argv, pid, tprefix, tid, "step2" );         //add the second breakpoint.
    printf( "[%s]: [%d] [%s] [%lu] [%s]\n", argv, pid, tprefix, tid, "step3" );

    return NULL;
}

void Child()
{
    pid_t pid = getpid();
    char prefix[] = "Child";
    printf( "[%s]: [%d] [%s]\n", prefix, pid, "step1" );
    return;
}

已知如果直接運行程序,那么輸出的內容如下:

[vfhky@typecodes pthread_key]$ gdb_pthread
[Parent]: [22648] [step1]
[Parent]: [22648] [thread] [139722467432256] [step2]
[Parent]: [22648] [thread] [139722467432256] [step3]
[Thread]: [22648] [thread] [139722450630400] [step2]
[Thread]: [22648] [thread] [139722450630400] [step3]
[Child]: [22649] [step1]
[vfhky@typecodes pthread_key]$
3 gdb調試

3.1 設置調試模式和Catchpoint

設置調試父子進程,gdb跟主進程,子進程block在fork位置。

[vfhky@typecodes pthread_key]$ gdb gdb_pthread
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-80.el7
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/vfhky/bin/gdb_pthread...done.
(gdb) set detach-on-fork off
#####catch讓程序在發生某種事件(fork、異常throw、異常catch、動態庫加載等)的時候停止運行
(gdb) catch fork 
Catchpoint 1 (fork)
(gdb) info b
Num     Type           Disp Enb Address            What
1       catchpoint     keep y                      fork
(gdb)

如下圖所示:

Linux多進程和多線程的一次gdb調試

3.2 開始gdb調試

(gdb) r                         ####運行到斷點/捕捉點(第17行處的fork函數,23873是子進程PID)
Starting program: /home/vfhky/bin/gdb_pthread 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".

Catchpoint 1 (forked process 23873), 0x00007ffff709b50c in __libc_fork () at ../nptl/sysdeps/unix/sysv/linux/fork.c:130
130       pid = ARCH_FORK ();
(gdb) bt                        #####查看堆棧情況
#0  0x00007ffff709b50c in __libc_fork () at ../nptl/sysdeps/unix/sysv/linux/fork.c:130
#1  0x00000000004007b4 in main (argc=1, argv=0x7fffffffe4c8) at gdb_pthread.c:17
(gdb) info threads              #######顯示運行的線程信息(23869是父進程的PID)
  Id   Target Id         Frame 
* 1    Thread 0x7ffff7fe1740 (LWP 23869) "gdb_pthread">這時使用如下命令查看當前CentOS系統所有進程的狀態:發現父進程PID為23869,通過fork產生的子進程為23873:[vfhky@typecodes ~]$ pstree -pul 同時,使用命令cat /proc/23869/status查看當前進程的詳細信息:進程PID為23869,它的父進程(即GDB進程)為23859,同時這也是追蹤進程ID,線程數Threads為1(共享使用該信號描述符的線程數,在POSIX多線程序應用程序中,線程組中的所有線程使用同一個信號描述符)。3.3 設置第一個斷點在程序的第18行設置斷點:(gdb) b gdb_pthread.c:18
Breakpoint 2 at 0x4007b7: file gdb_pthread.c, line 18.
(gdb) info b                        ######列出所有斷點和捕捉點
Num     Type           Disp Enb Address            What
1       catchpoint     keep y                      fork, process 23873                 ########子進程23873
        catchpoint already hit 1 time
2       breakpoint     keep y   0x00000000004007b7 in main at gdb_pthread.c:18
(gdb) 3.4 執行到第一個斷點(gdb) c                #####執行到第18行處的斷點
Continuing.
[New process 23873]                     #####父進程23869執行完第1個捕捉點的程序,產生子進程23873
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".

Breakpoint 2, main (argc=1, argv=0x7fffffffe4c8) at gdb_pthread.c:18            ##########父進程執行到第18行處的斷點
18              if(pid != 0)
(gdb) info threads                      ####查看所有運行的線程,有父進程23869和子進程23873
  Id   Target Id         Frame 
  2    Thread 0x7ffff7fe1740 (LWP 23873) "gdb_pthread" 0x00007ffff709b50c in __libc_fork () at ../nptl/sysdeps/unix/sysv/linux/fork.c:130
* 1    Thread 0x7ffff7fe1740 (LWP 23869) "gdb_pthread" main (argc=1, argv=0x7fffffffe4c8) at gdb_pthread.c:18
(gdb) info inferiors                    #####顯示正在調試的進程
  Num  Description       Executable        
  2    process 23873     /home/vfhky/bin/gdb_pthread                ########子進程
* 1    process 23869     /home/vfhky/bin/gdb_pthread                ########父進程
(gdb) info b                    #######查看當前所有的斷點
Num     Type           Disp Enb Address            What
1       catchpoint     keep y                      fork, process 23873 
        catchpoint already hit 1 time
2       breakpoint     keep y   <MULTIPLE>         
        breakpoint already hit 1 time
2.1                         y     0x00000000004007b7 in main at gdb_pthread.c:18 inf 2
2.2                         y     0x00000000004007b7 in main at gdb_pthread.c:18 inf 1
(gdb) 截圖如下:這時使用命令查看當前系統進程的狀態:發現此時仍然只有父進程23869和子進程23873。[vfhky@typecodes ~]$ pstree -pul 3.5 執行到第一個斷點此時如果切換到子進程23873(gdb) inferior 2
[Switching to inferior 2 [process 23873] (/home/vfhky/bin/gdb_pthread)]
[Switching to thread 2 (Thread 0x7ffff7fe1740 (LWP 23873))] 
#0  0x00007ffff709b50c in __libc_fork () at ../nptl/sysdeps/unix/sysv/linux/fork.c:130
130       pid = ARCH_FORK ();
(gdb) info inferiors                 #####顯示正在調試的進程 
  Num  Description       Executable        
* 2    process 23873     /home/vfhky/bin/gdb_pthread                #####子進程
  1    process 23869     /home/vfhky/bin/gdb_pthread                #####父進程
(gdb) 3.6 重新切換到父進程23869(gdb) inferior 1
[Switching to inferior 1 [process 23869] (/home/vfhky/bin/gdb_pthread)]
[Switching to thread 1 (Thread 0x7ffff7fe1740 (LWP 23869))] 
#0  main (argc=1, argv=0x7fffffffe4c8) at gdb_pthread.c:18
18              if(pid != 0)
(gdb) info inferiors                 #####顯示正在調試的進程
  Num  Description       Executable        
  2    process 23873     /home/vfhky/bin/gdb_pthread 
* 1    process 23869     /home/vfhky/bin/gdb_pthread 
(gdb) 3.7 設置第二個斷點并調試在第50行設置斷點繼續調試主進程(使父進程產生線程),其中父進程和線程到底是誰先執行是由內核調度控制的。(gdb) b gdb_pthread.c:50
Breakpoint 3 at 0x4008a7: gdb_pthread.c:50. (2 locations)
(gdb) c                    ######繼續執行代碼到第50行處的斷點
Continuing.
[Parent]: [23869] [step1]                              ######第33行父進程打印Parent()函數中的數據
[New Thread 0x7ffff6fdd700 (LWP 24024)]                ######第35行父進程創建了一個線程24024(LWP表示輕量級進程)
[Switching to Thread 0x7ffff6fdd700 (LWP 24024)]            #####已經自動切換到線程24024(LWP表示輕量。進程),也就是GDB繼續調試線程而不是父進程了。

Breakpoint 3, ParentDo (argv=0x7fffffffe390 "Thread") at gdb_pthread.c:50            ######線程24024阻塞在程序的第50行
50              printf( "[%s]: [%d] [%s] [%lu] [%s]\n", argv, pid, tprefix, tid, "step2" );
(gdb) 這時使用命令查看當前系統進程的狀態:存在父進程23869和子進程23873以及父進程創建的一個線程24024(線程用大括號{}表示)。[vfhky@typecodes ~]$ pstree -pul 同時,使用命令cat /proc/23869/status查看當前進程的詳細信息:進程PID為23869,它的父進程(即GDB進程)為23859,同時這也是追蹤進程ID,線程數Threads為2(當前父進程23869+線程24024)。3.8 查看第二個斷點處的調試信息(gdb) info inferiors                 #####顯示正在調試的進程 
  Num  Description       Executable        
  2    process 23873     /home/vfhky/bin/gdb_pthread                     ###子進程
* 1    process 23869     /home/vfhky/bin/gdb_pthread                     ###父進程 
(gdb) info threads         ####查看所有運行的線程,父進程23869、子進程23873、線程24024,由星號可以發現目前調試已經切換到了線程24024了。 
  Id   Target Id         Frame 
* 3    Thread 0x7ffff6fdd700 (LWP 24024) "gdb_pthread" ParentDo (argv=0x7fffffffe390 "Thread") at gdb_pthread.c:50
  2    Thread 0x7ffff7fe1740 (LWP 23873) "gdb_pthread" 0x00007ffff709b50c in __libc_fork () at ../nptl/sysdeps/unix/sysv/linux/fork.c:130
  1    Thread 0x7ffff7fe1740 (LWP 23869) "gdb_pthread" ParentDo (argv=0x7fffffffe3a0 "Parent") at gdb_pthread.c:50
(gdb) info b                #####查看設置的所有的斷點breakpoint和捕捉點catchpoint(共3個):
Num     Type           Disp Enb Address            What
1       catchpoint     keep y                      fork, process 23873 
        catchpoint already hit 1 time
2       breakpoint     keep y   <MULTIPLE>         
        breakpoint already hit 1 time
2.1                         y     0x00000000004007b7 in main at gdb_pthread.c:18 inf 2
2.2                         y     0x00000000004007b7 in main at gdb_pthread.c:18 inf 1
3       breakpoint     keep y   <MULTIPLE>         
        breakpoint already hit 1 time
3.1                         y     0x00000000004008a7 in ParentDo at gdb_pthread.c:50 inf 2
3.2                         y     0x00000000004008a7 in ParentDo at gdb_pthread.c:50 inf 1
(gdb) 3.9 如果手動切換到線程24024(gdb) thread 3
[Switching to thread 3 (Thread 0x7ffff6fdd700 (LWP 24024))]
#0  ParentDo (argv=0x7fffffffe390 "Thread") at gdb_pthread.c:50
50              printf( "[%s]: [%d] [%s] [%lu] [%s]\n", argv, pid, tprefix, tid, "step2" );
(gdb) info threads                   #####查看所有運行的線程
  Id   Target Id         Frame 
* 3    Thread 0x7ffff6fdd700 (LWP 24024) "gdb_pthread" ParentDo (argv=0x7fffffffe390 "Thread") at gdb_pthread.c:50
  2    Thread 0x7ffff7fe1740 (LWP 23873) "gdb_pthread" 0x00007ffff709b50c in __libc_fork () at ../nptl/sysdeps/unix/sysv/linux/fork.c:130
  1    Thread 0x7ffff7fe1740 (LWP 23869) "gdb_pthread" ParentDo (argv=0x7fffffffe3a0 "Parent") at gdb_pthread.c:50
(gdb) info inferiors                 #####顯示正在調試的進程  
  Num  Description       Executable        
  2    process 23873     /home/vfhky/bin/gdb_pthread 
* 1    process 23869     /home/vfhky/bin/gdb_pthread 
(gdb) 3.10 開始執行第二個斷點處的代碼(gdb) c
Continuing.
[Thread]: [23869] [thread] [140737337218816] [step2]            #####線程24024執行第50行處,打印數據
[Thread]: [23869] [thread] [140737337218816] [step3]            #####線程24024執行第51行處,打印數據
[Thread 0x7ffff6fdd700 (LWP 24024) exited]                      #####線程24024退出
[Switching to Thread 0x7ffff7fe1740 (LWP 23869)]                #####切換到父進程中去

Breakpoint 3, ParentDo (argv=0x7fffffffe3a0 "Parent") at gdb_pthread.c:50                #####父進程繼續停在第50行處的斷點
50              printf( "[%s]: [%d] [%s] [%lu] [%s]\n", argv, pid, tprefix, tid, "step2" );
(gdb) info inferiors                    ######列出正在調試進程(父進程23869和子進程23873),1前面的星號表示當前調試的進程(父進程23869)。 
  Num  Description       Executable        
  2    process 23873     /home/vfhky/bin/gdb_pthread 
* 1    process 23869     /home/vfhky/bin/gdb_pthread 
(gdb) info threads                     ######查看所有運行的線程
  Id   Target Id         Frame 
  2    Thread 0x7ffff7fe1740 (LWP 23873) "gdb_pthread" 0x00007ffff709b50c in __libc_fork () at ../nptl/sysdeps/unix/sysv/linux/fork.c:130            #####子進程23873
* 1    Thread 0x7ffff7fe1740 (LWP 23869) "gdb_pthread" ParentDo (argv=0x7fffffffe3a0 "Parent") at gdb_pthread.c:50          #####父進程23869
(gdb) 這時使用命令查看當前系統進程的狀態:存在父進程23869和子進程23873,其中線程24024已經結束了。[vfhky@typecodes ~]$ pstree -pul 3.11 繼續調試父進程此時,由于線程的退出,父進程作為自動選擇的要調試的線程。(gdb) c
Continuing.
[Parent]: [23869] [thread] [140737354012480] [step2]        #####父進程23869執行第50行
[Parent]: [23869] [thread] [140737354012480] [step3]        #####父進程23869執行第51行
[Inferior 1 (process 23869) exited normally]                #####正在調試的父進程23869退出
(gdb) info inferiors             ######顯示正在調試的進程
  Num  Description       Executable        
  2    process 23873     /home/vfhky/bin/gdb_pthread        #####fork創建的子進程23873
* 1    <null>            /home/vfhky/bin/gdb_pthread        #####fork創建的父進程23869已經退出 
(gdb) info threads              ####顯示正在運行的線程:只存在子進程23873,父進程23869已經退出 
  Id   Target Id         Frame 
  2    Thread 0x7ffff7fe1740 (LWP 23873) "gdb_pthread">這時使用命令查看當前系統進程的狀態:只有子進程23873(由內核init進程接管這個孤兒進程),父進程23869也已經結束了。[vfhky@typecodes ~]$ pstree -pul 再用ps ux命令查看子進程23873: 4 附錄在gdb中,經常用到的恢復程序運行和單步調試的命令有:continue        繼續運行程序直到下一個斷點(類似于VS里的F5)
next            逐過程步進,不會進入子函數(類似VS里的F10)
setp            逐語句步進,會進入子函數(類似VS里的F11)
until           運行至當前語句塊結束
finish          運行至函數結束并跳出,并打印函數的返回值(類似VS的Shift+F11)

“Linux多進程和多線程的一次gdb調試”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

岱山县| 长阳| 平定县| 新昌县| 辽宁省| 灵璧县| 闸北区| 石阡县| 永顺县| 通州区| 富顺县| 满洲里市| 遵义市| 乌审旗| 随州市| 依安县| 余干县| 高州市| 吴旗县| 宣城市| 阳江市| 洪雅县| 仁化县| 稻城县| 简阳市| 新龙县| 莲花县| 广水市| 罗源县| 神农架林区| 晋宁县| 清新县| 乌拉特后旗| 峨山| 山阳县| 沙洋县| 恭城| 汕尾市| 镇康县| 阿合奇县| 德惠市|