gdb 调试多进程中多线程的方法

  1. 示例代码
    首先,给出一个简单的示例程序,演示如何使用 fork 创建多个子进程并且每个进程内部创建多个线程。

示例代码 (main.cpp)

#include <iostream>
#include <thread>
#include <vector>
#include <unistd.h>
#include <sys/wait.h>
#include <cstdio>using namespace std;// 线程函数
void thread_function(int thread_id) {printf("Thread %d in process %d is running\n", thread_id, getpid());sleep(2);
}// 创建多个线程
void create_threads(const int threads_num) {vector<thread> threads;for (int i = 0; i < threads_num; i++) {threads.emplace_back(thread_function, i);}for (auto& th : threads) {if (th.joinable()) {th.join();}}
}int main() {const int num_processes = 8;const int num_threads = 8;vector<pid_t> child_pids;// 创建子进程printf("Started to create subprocesses\n");for (int i = 0; i < num_processes; i++) {pid_t pid = fork();if (pid == 0) { // 子进程create_threads(num_threads);exit(EXIT_SUCCESS);} else if (pid == -1) {perror("fork");exit(EXIT_FAILURE);} else { // 父进程记录 PIDchild_pids.push_back(pid);}}printf("End of subprocess creation\n");// 等待子进程结束for (pid_t pid : child_pids) {waitpid(pid, nullptr, 0);}cout << "All processes and threads completed." << endl;return 0;
}

代码说明:
主进程创建多个子进程:通过 fork() 创建 8 个子进程。 每个子进程创建多个线程:每个子进程中创建 8 个线程,通过 std::thread 启动线程并调用 thread_function。 进程和线程的输出:每个线程打印自己的 ID 和所属进程的 PID。
2. 编译程序
使用 g++ 编译程序时,确保添加 -g 选项以生成调试信息,并且链接线程库 -pthread。

Makefile

# 设置编译器
CXX = g++
# 设置编译选项
CXXFLAGS = -Wall
# 设置目标文件和输出可执行文件
TARGET = main
SRC = main.cpp# Debug 和 Release 的编译选项
DEBUG_FLAGS = -g -O0
RELEASE_FLAGS = -O3# 默认目标
all: debug release# 编译 Debug 版本
debug: CXXFLAGS += $(DEBUG_FLAGS)
debug: $(TARGET)_debug$(TARGET)_debug: $(SRC)$(CXX) $(CXXFLAGS) -o $@ $(SRC)# 编译 Release 版本
release: CXXFLAGS += $(RELEASE_FLAGS)
release: $(TARGET)_release$(TARGET)_release: $(SRC)$(CXX) $(CXXFLAGS) -o $@ $(SRC)# 清理目标文件
clean:rm -f $(TARGET)_debug $(TARGET)_release *.o

gdb ./multi_process_threads
3.1. 调试时如何处理 fork 和多进程
当程序执行到 fork() 时,GDB 默认只跟踪父进程。为了在 fork() 时调试子进程,你需要告诉 GDB 在 fork() 后应该跟踪父进程还是子进程。

跟踪子进程:

在 GDB 中输入以下命令来让调试器跟踪子进程:

(gdb) set follow-fork-mode child

跟踪父进程:

如果你想调试父进程而忽略子进程,可以设置为跟踪父进程:

(gdb) set follow-fork-mode parent

3.2. 设置断点
你可以在程序的关键部分设置断点,例如:

在 fork() 处设置断点:

(gdb) break fork

在 thread_function() 函数内部设置断点:

(gdb) break thread_function

在 main() 函数的开头设置断点:

(gdb) break main

3.3. 查看和切换进程
在调试多进程程序时,GDB 允许你查看当前的所有进程以及切换到不同的进程进行调试。

查看所有进程:

使用 info inferiors 命令查看当前调试的所有进程:

(gdb) info inferiors

GDB 会显示当前的进程和子进程信息,包括进程的 ID。

切换到特定进程:

通过 inferior 命令切换到一个特定的进程。例如,切换到进程 2:

(gdb) inferior 2

你可以在切换到进程后使用 continue 来继续调试当前进程。

3.4. 查看和切换线程
在调试多线程程序时,GDB 允许你查看当前线程列表并切换到特定线程。

查看线程列表:

使用 info threads 查看当前进程中的所有线程:

(gdb) info threads

GDB 会列出所有线程的 ID 和当前执行的位置。

切换到特定线程:

通过 thread <thread_id> 命令切换到指定的线程。例如,切换到线程 2:

(gdb) thread 2

切换到目标线程后,你可以使用 next (n) 或 step (s) 命令逐步调试该线程。

3.5. 锁定线程调度
为了避免 GDB 在多线程调试时自动切换线程,你可以使用 set scheduler-locking 命令来控制线程调度。

锁定当前线程:设置 scheduler-locking on 后,GDB 只会调度当前选中的线程,其他线程会被暂停。

(gdb) set scheduler-locking on

恢复调度所有线程:

(gdb) set scheduler-locking off

3.6. 单步调试
使用 next (n) 或 step (s) 命令单步调试程序时,默认情况下 GDB 会调度其他线程。这时,可以使用 set scheduler-locking 锁定线程,确保只步进当前线程。

(gdb) set scheduler-locking on
(gdb) thread 2  # 切换到线程 2
(gdb) next      # 只步进当前线程
  1. 总结
    在调试 fork 创建的多进程和多线程程序时,GDB 提供了多种工具和命令,帮助我们有效地查看和切换进程与线程。通过使用以下技巧,可以帮助你在复杂的多进程和多线程调试环境中更加高效地工作:
  • 使用 set follow-fork-mode 来选择调试父进程或子进程。
  • 使用 info inferiors 来查看并切换进程。
  • 使用 info threads 和 thread 命令来查看并切换线程。
  • 使用 set scheduler-locking 来锁定当前线程的调度,避免其他线程的干扰。
    这些方法将帮助你更好地调试涉及多个进程和线程的程序,并能够精确控制调试过程。希望这个博客的框架和内容可以帮助你顺利写出详细的文章!如果你需要进一步的帮助或调整内容,请随时告诉我。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/11888.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

20250202在Ubuntu22.04下使用Guvcview录像的时候降噪

20250202在Ubuntu22.04下使用Guvcview录像的时候降噪 2025/2/2 21:25 声卡&#xff1a;笔记本电脑的摄像头自带的【USB接口的】麦克风。没有外接3.5mm接口的耳机。 缘起&#xff1a;在安装Ubuntu18.04/20.04系统的笔记本电脑中直接使用Guvcview录像的时候底噪很大&#xff01; …

MySQL子查询

一、子查询的概述 1、理解&#xff1a;可以理解为嵌套查询&#xff0c;查询的内部进行查询 2、称谓规范&#xff1a;外查询&#xff08;主查询&#xff09;、内查询&#xff08;子查询&#xff09;&#xff0c;这种称呼是相对的。 子查询&#xff08;内查询&#xff09;在主查…

MongoDb user自定义 role 添加 action(collStats, EstimateDocumentCount)

使用 mongosh cd mongsh_bin_path mongosh “mongodb://user:passip:port/db”这样就直接进入了对应的db 直接输入&#xff1a; 这样 role “read_only_role" 就获得了3个 action&#xff0c; 分别是 查询&#xff0c;列举集合&#xff0c;集合元数据查询 P.S: 如果没有 …

结构体DMA串口接收比特错位

发送&#xff1a; 显示&#xff1a; uint16_t接收时候会比特错位。

经典本地影音播放器MPC-BE.

经典本地影音播放器MPC-BE 链接&#xff1a;https://pan.xunlei.com/s/VOIAZbbIuBM1haFdMYCubsU-A1?pwd4iz3# MPC-BE&#xff08;Media Player Classic Black Edition&#xff09;是来自 MPC-HC&#xff08;Media Player Classic Home Cinema&#xff09;的俄罗斯开发者重新…

python学opencv|读取图像(五十四)使用cv2.blur()函数实现图像像素均值处理

【1】引言 前序学习进程中&#xff0c;对图像的操作均基于各个像素点上的BGR值不同而展开。 对于彩色图像&#xff0c;每个像素点上的BGR值为三个整数&#xff0c;因为是三通道图像&#xff1b;对于灰度图像&#xff0c;各个像素上的BGR值是一个整数&#xff0c;因为这是单通…

【开源免费】基于Vue和SpringBoot的工作流程管理系统(附论文)

本文项目编号 T 193 &#xff0c;文末自助获取源码 \color{red}{T193&#xff0c;文末自助获取源码} T193&#xff0c;文末自助获取源码 目录 一、系统介绍二、数据库设计三、配套教程3.1 启动教程3.2 讲解视频3.3 二次开发教程 四、功能截图五、文案资料5.1 选题背景5.2 国内…

IntelliJ IDEA远程开发代理远程服务器端口(免费内网穿透)

IntelliJ IDEA远程开发代理远程服务器端口&#xff08;免费内网穿透&#xff09;&#xff08;JetBrains家的其他IDE应该也支持&#xff09; 之前看到宇宙第一IDE VS Code好像默认代理了远程的端口&#xff0c;但是一直没找到IDEA的同类功能&#xff0c;这次终于发现了 以Intell…

文字显示省略号

多行文本溢出显示省略号

STM32_SD卡的SDIO通信_DMA读写

本篇&#xff0c;将使用CubeMXKeil&#xff0c;创建一个SD卡的DMA读写工程。 目录 一、简述 二、CubeMX 配置 SDIO DMA 三、Keil 编辑代码 四、实验效果 实现效果&#xff0c;如下图&#xff1a; 一、简述 上篇已简单介绍了SD、SDIO&#xff0c;本篇不再啰嗦&#xff0c;…

智能小区物业管理系统推动数字化转型与提升用户居住体验

内容概要 在当今快速发展的社会中&#xff0c;智能小区物业管理系统的出现正在改变传统的物业管理方式。这种系统不仅仅是一种工具&#xff0c;更是一种推动数字化转型的重要力量。它通过高效的技术手段&#xff0c;将物业管理与用户居住体验紧密结合&#xff0c;无疑为社区带…

基于STM32景区环境监测系统的设计与实现(论文+源码)

1系统方案设计 根据系统功能的设计要求&#xff0c;展开基于STM32景区环境监测系统设计。如图2.1所示为系统总体设计框图。系统以STM32单片机作为系统主控模块&#xff0c;通过DHT11传感器、MQ传感器、声音传感器实时监测景区环境中的温湿度、空气质量以及噪音数据。系统监测环…

八. Spring Boot2 整合连接 Redis(超详细剖析)

八. Spring Boot2 整合连接 Redis(超详细剖析) 文章目录 八. Spring Boot2 整合连接 Redis(超详细剖析)2. 注意事项和细节3. 最后&#xff1a; 在 springboot 中 , 整合 redis 可以通过 RedisTemplate 完成对 redis 的操作, 包括设置数据/获取数据 比如添加和读取数据 具体整…

【Unity3D】Tilemap俯视角像素游戏案例

目录 一、导入Tilemap 二、导入像素风素材 三、使用Tilemap制作地图 3.1 制作Tile Palette素材库 3.2 制作地图 四、实现A*寻路 五、待完善 一、导入Tilemap Unity 2019.4.0f1 已内置Tilemap 需导入2D Sprite、2D Tilemap Editor、以及一个我没法正常搜出的2D Tilemap…

企微SCRM驱动企业私域流量营销与客户关系管理的智慧革新

内容概要 在当今竞争激烈的商业环境中&#xff0c;企微SCRM逐渐成为企业实现私域流量营销和优化客户关系管理的重要工具。它的出现不仅提升了企业的工作效率&#xff0c;也改变了传统的营销方式。那么&#xff0c;究竟什么是企微SCRM呢&#xff1f;简单来说&#xff0c;它是将…

数据库、数据仓库、数据湖有什么不同

数据库、数据仓库和数据湖是三种不同的数据存储和管理技术&#xff0c;它们在用途、设计目标、数据处理方式以及适用场景上存在显著差异。以下将从多个角度详细说明它们之间的区别&#xff1a; 1. 数据结构与存储方式 数据库&#xff1a; 数据库主要用于存储结构化的数据&…

前端力扣刷题 | 6:hot100之 矩阵

73. 矩阵置零 给定一个 m x n 的矩阵&#xff0c;如果一个元素为 0 &#xff0c;则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 法一&#xff1a; var setZeroes function(matrix) {let setX new Set(); // 用于存储需要置零的行索引let setY new Set(); //…

【编译系列】Torch.compile()训练编译——算子融合逻辑 工程化

1. 背景: torch.compile()中,Dynamo作为前端负责计算图的捕获,后端有inductor、tvm等进行编译优化。 Dynamo:在Python字节码层面注入pass,实现bytecode-to-bytecode的优化,通过对bytecode逐行进行解析构建FX GraphInductor:负责对FX Graph进行AOTAutograd生成joint-gra…

Docker 部署教程jenkins

Docker 部署 jenkins 教程 Jenkins 官方网站 Jenkins 是一个开源的自动化服务器&#xff0c;主要用于持续集成&#xff08;CI&#xff09;和持续交付&#xff08;CD&#xff09;过程。它帮助开发人员自动化构建、测试和部署应用程序&#xff0c;显著提高软件开发的效率和质量…

2025/2/3 云服务器数据库与idea相连

幸福就摆在你面前&#xff0c;你却把阴影当成山川瀑布&#xff0c;你说你无法幸福。 轻量应用服务器https://swasnext.console.aliyun.com/servers/cn-heyuanhttps://swasnext.console.aliyun.com/servers/cn-heyuanhttps://swasnext.console.aliyun.com/servers/cn-heyuanhttp…