精华内容
下载资源
问答
  • gdb调试多线程多进程
    2018-03-27 15:14:00

    GDB是linux下的调试利器,在c/c++程序开发过程中必不可少的。这里总结一下多进程和多线程的调试方法和技巧。

    多进程的调试:

    如下示例

    #include <sys/mman.h>
    #include <sys/stat.h>
    #include <fcntl.h>  
    #include <unistd.h>
    #include <stdio.h>
    #include <stdlib.h>
    static int glob = 23;
    
    void test()
    {
        int i = 0;
        printf("child pid: %d\n", getpid());
        while(1)
        {
            i++;
            sleep(3);
         printf("child running\n"); } }
    int main() { int pid = fork(); if(pid == 0) { test(); } else if(pid > 0){ printf("father pid : %d\n", getpid()); int n = 0; while(1) { n++; sleep(4);
           printf("father running\n"); } } wait(pid);
    return 0; }

    编译 gcc -g process.c -o process   -g一定要加上,否则没有调试信息。

    1. 如果我想要锁定子进程/父进程该怎样?

    这里在fork之后就会产生子进程, 如果我们要锁定子进程或者父进程可以使用  set follow-fork-mode [parent|child] 来完成。

    (gdb) set follow-fork-mode child
    (gdb) b 23
    Note: breakpoint 1 also set at pc 0x4006e4.
    Breakpoint 2 at 0x4006e4: file process.c, line 23.
    (gdb) info breakpoints 
    Num     Type           Disp Enb Address            What
    1       breakpoint     keep y   0x00000000004006e4 in main 
                                                       at process.c:23 inf 2, 1
        breakpoint already hit 1 time
    2       breakpoint     keep y   0x00000000004006e4 in main 
                                                       at process.c:23 inf 2, 1
    (gdb) delete breakpoints 2
    (gdb) r
    Starting program: /home/cps/桌面/IPC/process 
    
    Breakpoint 1, main () at process.c:23
    23        int pid = fork();
    (gdb) n
    [New process 37322]
    father pid : 37321
    [Switching to process 37322]
    24        if(pid == 0)
    (gdb) sparent running
    
    26            test();
    (gdb) parent running

    这里可以看到父进程一直在running, 跟踪子进程并没有停止父进程。 如果想要让父进程处于等待状态可以设置 set detach-on-fork [on | off]

    (gdb) set follow-fork-mode child 
    (gdb) b 23
    Breakpoint 1 at 0x4006e4: file process.c, line 23.
    (gdb) set detach-on-fork off
    (gdb) r
    Starting program: /home/cps/桌面/IPC/process 
    
    Breakpoint 1, main () at process.c:23
    23        int pid = fork();
    Missing separate debuginfos, use: debuginfo-install glibc-2.17-157.el7.x86_64
    (gdb) n
    [New process 37548]
    child pid: 37548
    child running
    child running
    child running
    child running

    可以看到父进程并没有执行,而是暂停状态。 只有子进程处于运行状态。

    2. 如何跟踪一个正在运行的进程?

    这里就要说到attach一个进程, 可以使用gdb -p pid execfilepath 来跟踪一个进程。

    [cps@cps IPC]$ gdb -p 37682 process
    GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-94.el7
    Missing separate debuginfos, use: debuginfo-install glibc-2.17-157.el7.x86_64
    (gdb) bt
    #0  0x00007fb8d8fad650 in __nanosleep_nocancel () from /lib64/libc.so.6
    #1  0x00007fb8d8fad504 in sleep () from /lib64/libc.so.6
    #2  0x00000000004006d0 in test () at process.c:16
    #3  0x00000000004006fc in main () at process.c:26
    (gdb) print i
    No symbol "i" in current context.
    (gdb) frame 2
    #2  0x00000000004006d0 in test () at process.c:16
    16            sleep(3);
    (gdb) print i
    $1 = 8
    (gdb) 

    这里的第一个print i 并没有打印东西,原因是没有进入堆栈, 我们进入test的堆栈后就可以查看变量。同时在gdb中也可以attach到一个进程中attach pid。

    3. 进程异常crash 怎样查看?

    这种情况下要打开coredump, 使用命令ulimit -c 1024 设置coredump开启。最后将dump文件和可执行文件 一同加载到gdb。 gdb coredump execfile。 进入gdb后 执行bt 和where 查看出错的地方。但是一般情况下的段错误用这种方法可很难查到。一般做法就是一步一步的调试,这种情况一般都是非法访问内存造成的,在最有可能出错的地方打断点。这种情况并没有较为直接的方法。

    多线程调试:

    1. 查看当前进程中的所有线程

    info threads  查看当前进程下的所有线程。前面有*代表当前处于的线程。

    thread id  可以切换当前处于的线程,bt查看线程的堆栈

    2. 锁定一个线程

    当我们在调试程序时, 若是想要调试某个线程,程序在执行过程中容易在线程之间来回切换, 我们可以选择一个线程后可以锁定它。

    thread id 选定这个线程

    set scheduler-locking on 可以用来锁定这个线程 只观察这个线程的运行情况。 当锁定这个线程时, 其他线程就处于了暂停状态。

    3. 锁定一个线程,让其他线程照常执行

    锁定一个线程让其他线程照常运行,这种用法在gdb 7.0以上的版本是支持的。可以如下设置gdb

    set target-async 1
    set pagination off
    set non-stop on

    这里的几个命令要在程序运行之前运行这些。

    多进程和多线程的调试技巧还有很多, 这里只是说了一些常见的基本用法。 至于其他的一些gdb用法可以查看gdb help。

     

    转载于:https://www.cnblogs.com/MaAce/p/8467182.html

    更多相关内容
  • gdb调试多线程多进程

    千次阅读 2017-03-03 09:28:06
    今天进行学习一下关于gdb调试多线程多进程的情况:gdb调试多进程尝试来调试多进程的程序,我们使用gdb进行调试程序,gdb的调试默认是调试父进程的,但是为了做到可以对父进程和子进程都做到调试,所以附加了调试子...

    今天进行学习一下关于gdb调试多线程和多进程的情况:

    gdb调试多进程


    尝试来调试多进程的程序,我们使用gdb进行调试程序,gdb的调试默认是调试父进程的,但是为了做到可以对父进程和子进程都做到调试,所以附加了调试子进程的功能。

    我们可以对fork出来的进程进行设置调试方法。

    follow-fork-mode的用法为:

    set follow-fork-mode parent/child

    如果你选择了parent,这个时候就是进行gdb调试父进程。
    如果你选择了child,这个时候就是进行gdb调试子进程。

    示例程序:

    #include<stdio.h>
    #include<unistd.h>
    #include<stdlib.h>
    int main()
    {
        int count =0;
        pid_t id=fork();
        if(id>0)
        {
            while(count++)
            {
                if(count>3)
                {
                    break;
                }
            }
    
        }
        else if(id==0)
        {
            int i=0;
            while(i<3)
            {
                i++;
                count--;
            }
        }
        else
        {
            perror("fork");
            exit(1);
        }
        return 0;
    }
    
    

    记得在编译代码的时候要加上-g选项。

    然后我们gdb打开调试文件。

    我们来进行调试子进程,
    ![enter description here][1]

    然后我们进行打断点进行调试,观察count的变化。

    首先打断点
    ![enter description here][2]

    然后运行至断点处。
    ![enter description here][3]

    然后我们进行单步执行,
    ![enter description here][4]
    我们发现调试跳过了父进程。 进入了子进程。
    ![enter description here][5]
    接下来我们就可以调试子进程的代码了。
    ![enter description here][6]

    上述就是进行子进程程序代码的调试,父进程的调试当然和子进程是一样的,所以我这里就不多说了。并且记得啊,如果你在调试的过程中更改mode是没有用的,只对下一次fork以后是起作用的。

    另外,gdb在多进程的调试中还有一个detach-on-fork参数。作用是指示GDB在fork之后是否断开某个进程的调试,或者都交由GDB控制:

    cpp
    set detach-on-fork on/off

    on表示断开调试follow-fork-mode指定的进程,off表示gdb将控制父进程和子进程

    所以我们也可以使用detach-on-fork的设置进行多个进程调试。

    首先打开进行调试,然后进去输入set detach-on-fork off,现在我们就可以进行多个进程调试了然后我们打上断点。运行至断点处。
    ![enter description here][7]

    然后我们n调用fork。fork以后,我们就可以使用i inferiors,这个命令是用来查看进程状态的,我们现在就可以发现,处在gdb的是两个进程都在调试。
    ![enter description here][8]

    然后我们可以通过inferior+进程序号的方式进行切换进程。例如inferior 2。这样就可以切换进程进行调试。
    ![enter description here][9]

    gdb多线程的调试


    接下来进行多线程的gdb的调试。
    首先我们写出我们的多线程的示例代码。

    #include<stdio.h>
    #include<pthread.h>
    void *id_run(void *arg)
    {
        printf("id%d run gdb success\n",(int )arg);
    }
    int main()
    {
        pthread_t id1;
        pthread_t id2;
    
        pthread_create(&id1,NULL,id_run,(void *)1);
        pthread_create(&id2,NULL,id_run,(void *)2);
    
        return 0;
    }
    

    一份简单的小代码,目的是为了向大家介绍多线程的gdb调试。

    首先我们来学习一下关于多线程的调试中gdb的一些命令。
    1. info threads:显示当前可调式的所有线程,gdb为每一个线程分配ID,这个ID后续操作的时候进行使用。
    ![enter description here][10]
    2. thread ID :切换到当前调试的线程的指定ID。

    ![enter description here][11]
    3. set scheduler-locking off|on|step :在使用step或者continue命令调试当前被调试线程的时候,其他线程也是同时执行的,通过这个命令就可以就可以实现这个要求,off是不锁定任何线程,也就是所有的线程都执行,这个是默认值。on是只有当前线程执行。step是在单步的时候,除了next过一个函数的情况意外,只有当前线程会执行。

    ![enter description here][12]
    4. set print thread-events :用于设定是否提示线程启动或停止时信息。
    5. thread apply ID command :让ID线程执行命令command。
    6. thread apply all command :让所有线程执行命令command。
    ![enter description here][13]

    展开全文
  • 1. gdb调试多进程 调试多进程有一种笨方法就是在fork之后子进程执行的代码中sleep一下。然后利用这段时间,通过gdb attach 子进程id。 不过在linux系统上(2.5.46之后),gdb是支持调试调试fork和vfork这种类型的...
    1. gdb调试多进程

    调试多进程有一种笨方法就是在fork之后子进程执行的代码中sleep一下。然后利用这段时间,通过gdb attach 子进程id。
    不过在linux系统上(2.5.46之后),gdb是支持调试调试fork和vfork这种类型的多进程程序的。

    #include <stdio.h>
    #include <stdlib.h>
    
    int main(int argc, char const *argv[]) {
        pid_t pid = fork();
        if (pid > 0) {
            printf("parent thread\n");
            exit(0);
        } else if (pid < 0) {
            perror("fork failed");
            exit(1);
        } else {
            printf("child thread\n");
        }
        return 0;
    }
    

    下面是具体的调试过程

    (gdb) show  detach-on-fork
    Whether gdb will detach the child of a fork is on.
    #这个参数默认是开启状态,意思就是当fork时,子进程默认detach
    (gdb) show follow-fork-mode
    Debugger response to a program call of fork or vfork is "parent".
    (gdb) show   follow-exec-mode
    Follow exec mode is "same".
    (gdb) info inferiors
      Num  Description       Executable        
    * 1    <null>            /root/demo_cpp2/./multi_thread 
    (gdb) set detach-on-fork off #关闭
    (gdb) info inferiors
      Num  Description       Executable        
    * 1    <null>            /root/demo_cpp2/./multi_thread 
    (gdb) n
    The program is not being run.
    (gdb) start
    Temporary breakpoint 1 at 0x40064c: file multi_thread.c, line 5.
    Starting program: /root/demo_cpp2/./multi_thread 
    [Thread debugging using libthread_db enabled]
    Using host libthread_db library "/lib64/libthread_db.so.1".
    
    Temporary breakpoint 1, main (argc=1, argv=0x7fffffffe378) at multi_thread.c:5
    5	    pid_t pid = fork();
    Missing separate debuginfos, use: debuginfo-install glibc-2.17-105.el7.x86_64
    (gdb) n
    [New process 10269]
    [Thread debugging using libthread_db enabled]
    Using host libthread_db library "/lib64/libthread_db.so.1".
    6	    if (pid > 0) {
    Missing separate debuginfos, use: debuginfo-install glibc-2.17-105.el7.x86_64
    (gdb) info inferiors
      Num  Description       Executable        
      2    process 10269     /root/demo_cpp2/./multi_thread 
    * 1    process 10265     /root/demo_cpp2/./multi_thread 
    #在这里就看到了所有进程
    (gdb) n
    7	        printf("parent thread\n");
    (gdb) 
    parent thread
    8	        exit(0);
    (gdb) inferior 2
    [Switching to inferior 2 [process 10269] (/root/demo_cpp2/./multi_thread)]
    [Switching to thread 2 (Thread 0x7ffff7fc8740 (LWP 10269))] 
    #0  0x00007ffff78bb50c in fork () from /lib64/libc.so.6
    # 通过inferior命令可以实现切换
    (gdb) n
    Single stepping until exit from function fork,
    which has no line number information.
    main (argc=1, argv=0x7fffffffe378) at multi_thread.c:6
    6	    if (pid > 0) {
    (gdb) n
    9	    } else if (pid < 0) {
    (gdb) n
    13	        printf("child thread\n");
    (gdb) show schedule-multiple
    Resuming the execution of threads of all processes is off.
    (gdb) set schedule-multiple on # 想让父子进程同时运行就设置成on
    (gdb) n
    child thread
    [Thread 0x7ffff7fc8740 (LWP 10265) exited]
    15	    return 0;
    (gdb) 
    

    总结一下,两个关键配置项

    • detach-on-fork 设为off,可同时调试父进程和子进程s
    • schedule-multiple 设为on,可同时运行父子进程
    2. 调试多线程

    gdb默认调试多线程,断点断在某个线程上时,其他线程也暂停。单步走时,其他线程也启动。这种场景,可能并不利于我们排查问题。
    如果我们指向锁定一个线程来排查问题,那么可以设置scheduler-locking线程锁来将其他线程"冻住"。
    set scheduler-locking on 锁定线程
    set scheduler-locking off 不锁定线程,默认模式
    set scheduler-locking step 单步执行时,锁定其他线程,不适用于continue, until 这些非单步操作

    参考:
    [0] https://sourceware.org/gdb/onlinedocs/gdb/Forks.html
    [1] https://sourceware.org/gdb/onlinedocs/gdb/All_002dStop-Mode.html

    展开全文
  • 使用gdb调试多线程的方法

    千次阅读 2021-01-03 23:19:01
    多线程死锁的调试方法: kill -11 得到 coredump 然后分析 在出现死锁时,kill -11 得到 coredump 然后分析 打印日志 把日志写的详细一些,可以反映出程序运行时的真是情况 gdb gdb法有个致命的缺陷,就是它...

    1. 多线程死锁的调试方法:

    1. 方法一: kill -11 得到 coredump 然后分析:
      在出现死锁时,kill -11 + 进程ID,得到 coredump 然后分析;
    2. 方法二: 打印日志 :
      把日志写的详细一些,可以反映出程序运行时的真实情况;
    3. 方法三: gdb单步调试:
      gdb法有个致命的缺陷,就是它打乱了多线程的真实调度顺序。
      多线程特定的错误往往是由于缺乏对共享数据的保护而导致的竞争状态的出现,而竞争状态的出现是具有偶然性的,取决于特定的调度次序;而当设置断点时,实际是将调度器的权限由系统交给调试者。这样在调试环境重现的,可能并不是bug时的真实情况。

    方法1: kill -11 调试coredump文件:

    操作步骤:

    kill -11 (pid)		//kill终止死锁进程
    gdb + 可执行程序 + coredump文件	//gdb开始查看coredump文件
    thread apply all bt		//查看所有线程的堆栈信息
    

    使用举例:

    一个死锁程序:test.c

    #include <stdio.h>
    #include <unistd.h> //sleep
    #include <pthread.h>
    
    pthread_mutex_t mtx_1 = PTHREAD_MUTEX_INITIALIZER;
    pthread_mutex_t mtx_2 = PTHREAD_MUTEX_INITIALIZER;
    
    void *func_1(void *arg) {
        printf("i am func_1\n");
        pthread_mutex_lock(&mtx_1);
        sleep(1);
        pthread_mutex_lock(&mtx_2);
    
        return NULL;
    }
    
    void *func_2(void *arg) {
        printf("i am func_2\n");
        pthread_mutex_lock(&mtx_2);
        sleep(1);
        pthread_mutex_lock(&mtx_1);
        
        return NULL;
    }
    
    int main() {
        pthread_t tid_1;
        pthread_t tid_2;
    
        pthread_create(&tid_1, NULL, func_1, NULL);
        pthread_create(&tid_2, NULL, func_2, NULL);
    
        pthread_join(tid_1, NULL);
        pthread_join(tid_2, NULL);
    
        return 0;
    }
    

    上述示例程序是一个会产生死锁的错误程序:
    线程1拿到互斥锁A等待互斥锁B,线程2拿到互斥锁B等待互斥锁A。

    调试过程:

    ps -aux | grep test		//查询test程序的进程号
    
    kill -11 11440			//强制test进程产生coredump文件
    
    gdb ./test core.test.11440	//开始调试coredump文件
    
    
    (gdb) thread apply all bt
    
    Thread 3 (Thread 0x7f5739841700 (LWP 11441)):
    #0  0x00007f5739c1837d in __lll_lock_wait () from /lib64/libpthread.so.0
    #1  0x00007f5739c11e5d in pthread_mutex_lock () from /lib64/libpthread.so.0     <===========
    #2  0x000000000040073f in func_1 (arg=0x0) at test.c:8                          <===========
    #3  0x00007f5739c0f73a in start_thread () from /lib64/libpthread.so.0
    #4  0x00007f5739949e0f in clone () from /lib64/libc.so.6
    
    Thread 2 (Thread 0x7f5739040700 (LWP 11442)):
    #0  0x00007f5739c1837d in __lll_lock_wait () from /lib64/libpthread.so.0
    #1  0x00007f5739c11e5d in pthread_mutex_lock () from /lib64/libpthread.so.0     <===========
    #2  0x000000000040077b in func_2 (arg=0x0) at test.c:17                         <===========
    #3  0x00007f5739c0f73a in start_thread () from /lib64/libpthread.so.0
    #4  0x00007f5739949e0f in clone () from /lib64/libc.so.6
    
    Thread 1 (Thread 0x7f573a020700 (LWP 11440)):
    #0  0x00007f5739c109bd in pthread_join () from /lib64/libpthread.so.0
    #1  0x00000000004007cd in main () at test.c:26
    

    通过查看所有线程的bt堆栈信息,可以看到子线程 11441 和 11442 在出现死锁时正在执行的函数分别是:

    test.c 文件的第 8 行 和 第 17 行,执行的函数都是 pthread_mutex_lock() 。

    这样就可以定位到引入死锁的位置。

    (通过 coredump 文件只能定位到出现死锁时各线程的堆栈情况、正在执行的函数,至于出现死锁的逻辑原因,还要我们去亲自分析代码。 coredump 只是一个辅助定位手段。)

    方法2:打印日志

    一个打印技巧:

    printf("%-20s, %3d, %6d, content = %d\n", 
    		__func__, __LINE__, gettid(), content);
    

    在调用printf打印时,可以使用C语言中的“预定义标识符”,包括:

    __LINE__	:	当前程序的行号,十进制整型,%d
    __FILE__	:	当前源文件名,字符串,%s
    __DATE__	:	日期,字符串,%s
    __TIME__	:	时间,字符串,%s
    

    另外:

    __func__	:	指示所在的函数,字符串,%s
    				这个是由gcc支持的
    

    方法3:gdb单步调试:

    gbb ./active_threadpool		//直接开始执行多线程程序
    
    start
    r					//run
    
    info inferiors		//查看进程信息
    info threads		//查看线程信息
    
    thread (n)			//切换到某个线程上去
    					//注意参数 n 是gdb中的序号(1, 2, 3...),而不是 LWP 的tid (16088)
    
    bt					//查看程序的调用栈信息,显示的是调用栈中的函数
    
    b (n)				//breakpoint,打断点,参数n可以是行号或者【函数名】,如 `b 15` 或者 `b main`
    info b
    
    n					//next
    s					//step
    
    c					//continue,使程序“恢复执行”,继续执行到下一个断点处,如果没有下一个断点则一直执行到程序的最后
    fin					//finish,当不小心单步进入了原本希望单步越过的函数时,使用fin返回
    
    set (var)			//修改变量的值
    
    thread apply all bt				
    thread apply [thread-id-list]/[all] (args)		//在一系列线程上执行命令
    
    print (var)				
    print (struct)			//如果打印结构体,直接会{ }打印出结构体所有成员的值
    print (p)				//如果打印指针,只会打印指针本身的值
    print (*p)				//比如: print *pool;  会把指针所指向的变量的内容打印出来
    
    set print pretty on		//美化打印,换行打印输出
    
    set scheduler-locking off|on|step	//是否让所有的线程在gdb调试时都执行
    									//off :(缺省)不锁定任何线程,也就是所有线程都执行
    									//on :只有当前被调试的线程能够执行
    									//step :阻止其他线程在当前线程【单步调试】的时候(即step时),抢占当前线程。只有当next、continue、util、finish的时候,其他线程才能重新运行。
    
    set follow-fork-mode parent|child	//用于调试多进程:fork之后是要调试父进程还是调试子进程
    
    attach (thread-ID)			//用于调试正在运行的进程,它允许开发人员中断程序,并查看其状态,之后还能让程序正常的执行
    
    

    ① start 和 run 指令的比较:

    run和start指令都可以用来在GDB调试器中启动程序,二者的区别在于:
    run指令会一直执行程序,直到执行结束或遇到第一个断点处;
    start执行会执行至main函数的其实位置处停下来。

    可以这样理解:
    使用start指令启动程序,完全等价于先在main()主函数起始位置设置一个断点,然后再使用run指令启动程序。

    另外,程序执行过程中使用run或者start指令,表示的是重新启动程序。

    ② next 与 step 指令的比较:

    如果下一条要执行的语句是普通语句,那么step和next的行为是一模一样的:执行完那条普通语句,再次暂停住;

    如果下一条要执行的语句是一个函数调用语句,那么step就会进入到这个函数之中,next就会直接越过这个函数(gdb在本地里悄悄的把这个函数执行完)。

    ③ continue 和 finish 指令的比较:

    continue:使程序“恢复执行”,继续执行到下一个断点处,如果没有下一个断点则一直执行到程序的最后;

    finish:当不小心单步进入了原本希望单步越过的函数时,使用fin返回。

    2. 背景知识:

    2.1 什么是“主线程”:

    主线程是当一个程序启动时,就有一个进程被操作系统(OS)创建,与此同时一个线程也立刻运行。

    因为它是程序开始时就执行的,如果你需要再创建线程,那么创建的线程就是这个主线程的子线程。每个进程至少都有一个主线程。

    主线程的重要性体现在两个方面:
    (1)其他线程必须由主线程来创建;
    (2)主线程应该是最后一个退出,否则如果主线程提前退出,其他子线程也会跟着退出,可能无法执行完成任务。

    对于如何实现让主线程等待子线程全部执行完了再退出,目前掌握两种方法:
    (1)主线程中调用 pthread_join() 等待所有线程执行完毕,但这种情况下子线程不能detach,子线程退出后的资源要考主线程来回收;
    (2)实现一个“wait方法”(参考线程池的ntyThreadPoolWait),在主线程将任务全部传递给线程池后,调用 pthread_cond_wait() 等待在一个 wait_cv 条件变量上,当线程池处理完所有的任务后,signal 唤醒主线程继续向下执行,这种情况下子线程是可以 detach 的。

    2.2 Linux下的 ps 命令:

    ps = process status(进程状态),用于显示当前进程的状态,类似于Windows下的任务管理器

    ps命令的参数众多,几个常用的:

    ps -a			//列出所有进程
    ps -au			//显示更多的信息
    ps -aux			//显示所有包含其他使用者的进程
    

    ps -aux 查看到的Linux进程的几种状态:

    R	:	running,正在运行 或 在运行队列中等待
    S	:	sleeping,正在休眠(例如阻塞挂起)
    T	:	停止或被追踪(停止:进程收到SIGSTOP、SIGSTP、SIGINT、SIGOUT信号后停止运行)
    Z	:	僵尸进程(进程已终止,但进程描述符存在,直到父进程调用wait4()系统调用后释放)
    D	:	不可中断(收到信号也不会唤醒或运行,进程必须等待中断发生)
    

    2.3 线程的查看:

    ps -aux  | grep a.out		//查看进程
    ps -aL	| geep a.out		//查看线程
    pstree -p (主线程ID)			//查看线程关系,树状图
    

    2.4 gettid() 和 pthread_self()的区别:

    gettid() 获取的是内核中真实线程ID,pthread_self() 获取的是相对于子进程的线程控制块的首地址。

    如何使用 gettid():

    #include <sys/syscall.h>
    #include <unistd.h> //pid_t
    
    pid_t gettid()
    {
    	return syscall(SYS_gettid);
    }
    

    2.5 kill 命令:

    为什么一定要用 kill -11 才能产生coredump文件?而 kill -9 却不会产生coredump文件?

    kill命令是向进程发送信号:

    kill + (signal) + (pid)
    

    “kill -11”、“kill -9”这些数字实际上代表的是信号的值:

    #define SIGKILL		9
    #define SIGSEGV		11
    

    “9” 表示的是强制终止进程,SIGKILL信号不能被屏蔽,不能被忽略;
    “11” 表示的是强制生成coredump文件,相当于是向未定义的内存去写入数据。

    “CTRL + C” 相当于是 发送 SIGINT(2) 。

    展开全文
  • gdb调试多线程多进程一.多线程调试多进程调试 一.多线程调试 代码 1 #include <thread> 2 #include <vector> 3 #include <iostream> 4 #include <stdio.h> 5 #include <unistd.h&...
  • 推荐看这个:...排除步骤 1.ps -eo pid,lstart,cmd | grep proname找出进程的pid2.gdb attach pid。使用gdb attach可以调试正在运行的进程,这对数据不正常的程序很有效。3.inf...
  • 调试多线程程序的方法 使用gdb将程序跑起来,然后按下CTRL+C中断程序,使用info threads命令查看当前进程有多少线程;使用thread 线程编号可以切换到对应的线程,使用bt命令查看对应的线程从顶层到底层的函数调用...
  • gdb的简介和功能:gdb是GNU开发的一个在Unix,Linux上使用的C/C++和汇编语言程序的调试工具,它主要帮助用户在调试程序时完成以下工作: 启动程序,按照用户要求影响程序的运行 设置断点,在指定位置停止 当程序停止...
  • GDB调试多线程

    2018-04-17 17:54:40
    段错误不好调试,在于不好定位,GDB可以生成core文件。但是有时候,无法生成core文件,需要添加断点逐步调试多进程不容易追踪到子进程,根据文档中的步骤,可以跟踪子进程。
  • gdb+vscode进行调试6——gdb调试多线程命令札记
  • 一、调试的指令1.list命令list linenum 显示程序第linenum行的周围的程序list function 显示程序名为function的函数的源程序list 显示当前行后面的源程序list - 显示当前行前面的源程序2.run(r):运行命令run ...
  • 介绍: gdb是Linux环境下的代码调试工具。 2>使用:需要在源代码生成的时候加上 -g 选项. 3>开始使用: gdb binFile 4>退出:ctrl + d 或 quit 5>调试过程中的常用命令: list/l 行号:显示binFile源...
  • GDB调试多进程/线程

    2021-07-17 23:16:49
    多线程调试 选择调试进程GDB中有两个选项来确定调试进程: follow-fork-mode,设置调试哪个进程 detach-on-fork,GDB在fork之后是否断开(detach)某个进程调试 这两个选项的参数组合起来的效果如下表 ...
  • gdb调试多进程多线程

    万次阅读 多人点赞 2017-06-10 16:32:25
    一,gdb的基础知识1>介绍: gdb是Linux环境下的代码调试工具。 2>使用:需要在源代码生成的时候加上 -g 选项. 3>开始使用: gdb binFile 4>退出:ctrl + d 或 quit 5>调试过程中的常用命令: list/l 行号:显示...
  • 常用命令 命令 ...让一个或者线程执行GDB命令command thread apply all command 让所有线程执行GDB命令command b xxxx thread thread_nums 给thread_nums线程的xxxx函数打断点 set sche
  • 目录 GDB多线程查看崩溃时线程的堆栈 线程的查看以及利用gdb调试多线程 GDB 调试多线程和多进程总结 排除步骤 调试多进程 一、gdb的基础知识复习 二、使用gdb调试多进程 三,gdb 调试多线程 四、设置线程名字(便于...
  • 多线程调试 (一)多线程调试命令 shell的命令: (1)查看当前运行的进程:ps aux | grep book (2)查看当前运行的轻量级进程:ps -aL | grep book (3)查看主线程和子线程的关系:pstree -p 主线程id gdb的命令...
  • GDB是GUN开源组织发布的一个强大的UNIX下的程序调试工具。或许,平时大家更加习惯图形界面的调试,比如VS上的IDE调试;但是如果我们在UNIX或Linux下做软件,我们呢就更加需要熟练GDB这个调试工具。
  • Linux:多线程——死锁以及使用gdb调试多线程程序时常用的命令死锁死锁产生的四个必要条件预防死锁使用gdb调试多线程程序时常用的命令 死锁 死锁:指在一组进程中的各个进程均占有不是放的资源,但因相互申请被其他...
  • GDB调试多线程切换

    千次阅读 2020-08-08 21:43:17
    本文介绍GDB调试多线程的程序
  • 2、生成core文件 测试源码 3、调式正在运行的程序 测试程序 4、调试多进程程序 测试程序 5、调试多线程程序
  • GDB调试程序 在linux中使用gdb调试时我们可以在编译的时候加上-g即可。如果你用一个makefile文件做处理,只需要在里面加上调试信息。gdb调试的是正在运行的程序,而不是我们已经编写好的.c文件。 如果我们没有添加-g...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 16,582
精华内容 6,632
关键字:

gdb调试多线程多进程