用户态程序阻塞原因_ucore 拓展之——用 gdb 调试程序从用户态到内核态再回到用户态的整个流程

ucore 拓展之——用 gdb 调试程序从用户态到内核态再回到用户态的整个流程

说起来你可能不信, 为了调试用户态程序, 我第一反应是在 ucore 上装个 gdb! 当我还在故作深沉考察可行性的时候,stackoverflow 已经给了我一句劝告: gdb 比你想象的要更强大.

每个程序员, 每次解决一个未曾谋面的新问题后, 都会持续大概 5 分钟的自我陶醉, 我可真太牛逼了, 然后冷静分析下来发现, 其实这已经是二三十年前的技术了...但不管怎样, 都要有从不知道到知道的过程, 姑且记录下来.

ls 为例, 起码要向控制台输出当前文件列表, 即多次调用 printf; 而printf会进行系统调用write,再往后就是中断的生成, 派发和处理, 再往后io系统向stdin输出信息...如何跟踪?

答案: 多用 (gdb)file 命令.

  1. Makefile中添加下列目标, 令 qemu 把输出重定向到串口的标准输出:
dbg-u2k: $(UCOREIMG) $(SWAPIMG) $(SFSIMG)
    $(V)$(QEMU) -S -s -serial mon:stdio $(QEMUOPTS)
  1. 清空 .gdbinit, 除非了解它的作用;
  2. 定位到 ucore 项目根目录下, 执行 make dbg-u2k, ucore 编译完毕并被 qemu 加载,停留在第一条指令之前;
  3. 此时在另一终端执行gdb bin/kernel, 并target remote localhost:1234连接上 qemu, 观察到熟悉的提示信息.事实上到此为止与往常没有明显不同. 现在可以键入c,让内核自由运行,直到运行了shell.
  4. 现在的状态是什么? 你可以枉顾 gdb 的存在,在 ucore 执行你的用户程序,如下图:

3bfd890188dc891779d67a02951298d7.png
  1. 但是此时 gdb 加载的是 kernel 的符号.现在只需Ctrl C中断 gdb,再键入file disk0/ls,即可加载 ls 的符号! 这是...热加载?
  2. 此时键入b main,就可以像调试普通用户态程序一样调试 ls 了, 如下:

b15945ba6caea2e590992f426b79b841.png
  1. 同样,当在用户程序遇到系统调用时不用慌,跟进去,用 file切成内核即可!比如我们跟踪到了函数lsstat, 想跟入 printf 一探究竟:

bf0b78a682af0b9502ace431f892ebaf.png

最终我们一路跟踪到user/libs/syscall.csyscall, 即将陷入中断.此时再执行n,就跟不到代码了.

b32f9d0b5e292e3eee3a935e7549710d.png

此时只需键入file bin/kernel,就进入了内核态的调试环境!再打个断点, 如b trap, 就接住这个系统调用了!

b9805006042e6d31aa6b0275124d0ee4.png

我想,linux 内核调试起来大概也是如此的流程?

相关原理

当在 gdb 命令窗口键入 Ctrl C, 发生了什么?

首先我们可以看到 gdb 的输出:

Program received signal SIGINT, Interrupt.

事实是: GDB帮用户拦截了致命的信号.

键入(gdb) info signals可以查看 gdb 帮我们拦截的信号:

Signal        Stop  Print   Pass to program Description

SIGHUP        Yes   Yes Yes     Hangup
SIGINT        Yes   Yes No      Interrupt
SIGQUIT       Yes   Yes Yes     Quit
SIGILL        Yes   Yes Yes     Illegal instruction
SIGTRAP       Yes   Yes No      Trace/breakpoint trap
SIGABRT       Yes   Yes Yes     Aborted
...

可以观察到, Ctrl C 对应的 SIGINT 信号被 gdb 所捕获并输出, 并没有真正传递给进程.所以我们可以利用这个间隙来调整 gdb 的选项,就像刚才一样加载其他文件的符号,有了从用户态到内核态来去自由的机会.不过这也许只是手段之一吧,以后有了其他发现再回来更新.

欢迎联系/交流/质疑.

更多资料

  • Debugging with GDB, 5.4 Signals
  • Stack Overflow: Debugging user-code on xv6 with gdb
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值