gdb调试多线程底层实现原理

哈喽,我是子牙老师,一个手写过操作系统、编程语言、Java虚拟机、docker、Ubuntu系统,玩透Windows内核、Linux内核...的硬核男人

现实中,我们写的程序一般都是多线程程序。如果多线程程序出问题了,就需要用到gdb的多线程调试功能,非常方便,直接通过thread tid切到可能存在问题的线程,单步执行,看堆栈、寄存器、内存,很快就能找到错误原因

这么强大的功能背后,底层实现原理是什么呢?我们自己写调试器,该如何实现呢?本篇文章为你全方位揭晓!本篇文章看完,gdb远程调试的all,你就过关了!

本篇文章需要前面文章的功底,如果你没看过,建议看看《从零手写gdb调试器》《调试器是如何让代码停下来的》《gdb调试器底层实现原理》《gdb的放过去是如何做到的》

以下,enjoy

Linux内核层面

刚开始接触,难免丈二和尚摸不着头脑,那不妨猜测一下,Linux内核层面会如何实现呢?

那也不能无凭无据的乱猜对吧,根据我们研究调试器的经验+使用gdb调试多线程程序的经验,肯定是Linux内核创建一个线程,就把这个创建线程事件报告给调试器进程。会以何种方式报告呢?信号。什么信号呢?不知道,得看代码找证据。那就开始找证据

研究Linux内核,肯定要借助单步调试环境。那在哪下断点呢?得知道使用pthread_create创建线程,进入内核后,调用的是哪个函数。课程《实战Linux内核》三期讲过,__do_fork函数

通过单步调试Linux内核,跟踪代码执行,发现确实跟我们猜想的一样

那发送的是什么信号呢?进入函数ptrace_event_pid就能找到答案

也是SIGTRAP信号,但是还拼接了点东西。这个要记住,后面写调试器代码会用上。这个event是多少呢?3

用户态实现

如果trace值为0,就不会执行ptrace_event_pid,发送SIGTRAP信号。想想也有道理,如果创建线程,不管三七二十一,都给父进程发SIGTRAP信号,是有点多此一举了。那这个动作肯定是由用户触发了,用户告诉Linux内核:嘿,大兄弟,有线程创建知会我一声

用户怎么告诉内核呢?这样

进入Linux内核后呢?这样

这样,被调试进程的ptrace上就多了很多东西,这个多出来的东西会影响被调试进程创建线程的参数clone_flags(这个环节在pthread库中,偷个懒,不找了)

最终会执行ptrace_event_pid函数,给调试进程发送SIGTRAP信号

妙不妙?反正我研究Linux内核,读Linux内核源码,特别上瘾!

写调试器

来,开干

手写告诉Linux内核:大兄弟,打个桩,有线程创建,告诉我

终于,等了许久,有线程创建了,SIGTRAP信号来了

捕捉到线程创建,完整的操作应该是这样

你在gdb中,使用info threads查看所有的线程信息,通过thread tid能够切换线程,都是以这个代码为基础实现的,来看看完整的代码

至此,gdb调试多线程的底层原理,你应该全部掌握了吧!

如果你也想像我一样,打通所有技术认知,可以随意玩汇编、C语言、Linux用户态、Linux内核态、调试器,欢迎跟我学习。全国唯一一个人做了整个计算机体系课程的人:手写JVM、手写操作系统、实战Linux内核、手写Ubuntu Linux系统、手写编程语言、手写docker、手写调试器

相关推荐
Rose sait26 分钟前
【环境配置】Linux配置虚拟环境pytorch
linux·人工智能·python
叶之香1 小时前
CentOS/RHEL 7、8安装exfat和ntfs文件系统
linux·运维·centos
一世琉璃白_Y1 小时前
pg配置国内数据源安装
linux·python·postgresql·centos
不过普通话一乙不改名1 小时前
Linux 内核开发入门:从环境配置到 Hello World 实战
linux·运维
乖乖是干饭王1 小时前
Linux 内核 Kbuild 中的 ld 调用机制
linux·c·makefile
Trouvaille ~2 小时前
【Linux】理解“一切皆文件“与缓冲区机制:Linux文件系统的设计哲学
linux·运维·服务器·操作系统·进程·文件·缓冲区
ITKEY_2 小时前
archlinux 通过wpa_supplicant 连接wifi固定ip设置方法
linux·固定ip
幸存者letp3 小时前
Python 常用方法分类大全
linux·服务器·python
知识分享小能手3 小时前
Ubuntu入门学习教程,从入门到精通,Linux操作系统概述(1)
linux·学习·ubuntu