Linux 多进程程序调试实例(一) --GDB调试fork函数

简单版多进程程序实例

  1. 代码
// fork 生成子进程
// 父进程调用 fork 返回的是子进程的进程ID,子进程调用该函数返回的是 0
#include<iostream>
#include<unistd.h>
#include<cstdio>
int main()
{
    
    pid_t pid = fork();
    if( 0 == pid ) {
        std::cout << "hi, I'am a child process and the process id is " << getpid() << std::endl;
    }
    else if(pid > 0){
        std::cout << "hi, I'am a parent process and the process id is " << getpid() << std::endl;
    }
    else{
        perror("fork");
    }
    return 0;    
}
  1. 调试命令
follow-fork-mode detach-on-fork Description
parent on 只调试父进程(GDB 模式)
child on 只调试子进程
parent off 同时调试两个进程, GDB 跟父进程,子进程阻塞在 fork 处
child off 同时调试两个进程, GDB 跟子进程,父进程阻塞在 fork 处
  • show follow-fork-mode
    • 查看调试的进程
  • show detach-on-fork
    • 查看调试的进程模式
  • set follow-fork-mode [parent/child]
    • 切换 GDB 调试进程为 parent/child
  • set detach-on-fork off
    • GDB 跟踪 follow-fork-mode 的进程,另一个进程阻塞在 fork 处
  • info inferior
    • 查询正在调试的进程
  • inferior [number]
    • 切换到对应的进程进行调试
  1. 调试步骤
  • GDB 进入到可执行程序中调试
  • 先查看当前 GDB 对于多进程调试的参数
    • show follow-fork-mode
    • show detach-on-fork
  • 设置 GDB 调试父进程,子进程阻塞在 fork 函数处
    • set detach-on-fork off
  • 然后执行程序,运行到 fork 的下一行代码
  • 然后查看当前正在调试的进程
    • info inferiors
  • 选择一个进程进行调试
    • inferior [number_id] 调试第 [number_id] 个进程
    • 此时另外一个进程阻塞在 fork 处
  • 当前该进程调试完毕以后,想要调试另外一个进程,就继续执行上述中 inferior 命令切换到对应的进程
    • 切换完进程以后,可以直接执行 c 运行到断点处,或者 fork 处
  1. 调试记录
(gdb) l
1       #include<iostream>
2       #include<unistd.h>
3       #include<cstdio>
4       int main()
5       {
6           
7           pid_t pid = fork();
8           if( 0 == pid ) {
9               std::cout << "hi, I'am a child process and the process id is " << getpid() << std::endl;
10          }
(gdb) b 8
Breakpoint 1 at 0x400977: file multiprocess.cpp, line 8.
(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) set detach-on-fork off
(gdb) r
Starting program: /home/user/Desktop/code/ProgramDebug/multiprocess/multiprocess 
[New process 12353]
Reading symbols from /usr/lib/debug/lib/x86_64-linux-gnu/libc-2.23.so...done.
Reading symbols from /usr/lib/debug/lib/x86_64-linux-gnu/libm-2.23.so...done.
Reading symbols from /usr/lib/debug/lib/x86_64-linux-gnu/ld-2.23.so...done.

Thread 1.1 "multiprocess" hit Breakpoint 1, main () at multiprocess.cpp:8
8           if( 0 == pid ) {
(gdb) info inferiors 
  Num  Description       Executable        
* 1    process 12349     /home/user/Desktop/code/ProgramDebug/multiprocess/multiprocess 
  2    process 12353     /home/user/Desktop/code/ProgramDebug/multiprocess/multiprocess 
(gdb) n
11          else if(pid > 0){
(gdb) 
12              std::cout << "hi, I'am a parent process and the process id is " << getpid() << std::endl;
(gdb) 
hi, I'am a parent process and the process id is 12349
17          return 0;    
(gdb) 
18      }(gdb) 
__libc_start_main (main=0x400966 <main()>, argc=1, argv=0x7fffffffdf58, init=<optimized out>, 
    fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffdf48)
    at ../csu/libc-start.c:325
325     ../csu/libc-start.c: No such file or directory.
(gdb) l
320     in ../csu/libc-start.c
(gdb) c
Continuing.
[Inferior 1 (process 12349) exited normally]
(gdb) info inferior 
  Num  Description       Executable        
* 1    <null>            /home/user/Desktop/code/ProgramDebug/multiprocess/multiprocess 
  2    process 12353     /home/user/Desktop/code/ProgramDebug/multiprocess/multiprocess 
(gdb) inferior 2
[Switching to inferior 2 [process 12353] (/home/user/Desktop/code/ProgramDebug/multiprocess/multiprocess)]
[Switching to thread 2.1 (process 12353)] 
#0  0x00007ffff775749a in __libc_fork () at ../sysdeps/nptl/fork.c:145
145     ../sysdeps/nptl/fork.c: No such file or directory.
(gdb) c
Continuing.

Thread 2.1 "multiprocess" hit Breakpoint 1, main () at multiprocess.cpp:8
8           if( 0 == pid ) {
(gdb) n
9               std::cout << "hi, I'am a child process and the process id is " << getpid() << std::endl;
(gdb) 
hi, I'am a child process and the process id is 12353
17          return 0;    
(gdb) 
18      }(gdb) 

调试过程总结

  1. GDB启动,程序运行之前设置多进程调试
    • set detach-on-fork off
  2. 断点设置在 fork 处
  3. 执行程序 (run)
  4. 程序执行到断点处之后,执行继续的命令 continued(c)
    • 此时默认执行的线程是 show follow-fork-mode 线程,如果想要默认执行另外一个进程,则在步骤 1 处设置
    • 设置的命令为 set follow-fork-mode child (默认调试parent)
  5. 查看正在调试的进程
    • info inferior
  6. 切换调试的进程
    • inferior [number_id]
  7. 执行 continute 命令,运行到断点处(fork处在的行)
  8. r/inferior 切换回父进程
posted @   王清河  阅读(1376)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
历史上的今天:
2020-01-16 shell编程题(二十五)
点击右上角即可分享
微信分享提示