c - 是否可以在 gdb 中确定线程是否在内核或用户空间中执行(或阻塞)?
问题描述
考虑以下程序。
#include <unistd.h>
int main(){
sleep(1000);
}
如果我们strace
在这个程序上运行,在 long sleep 之前出现的最后一行如下。
nanosleep({1000, 0},
当程序处于休眠状态时,代码正在操作系统内核中执行(可能被阻塞)。
当我在 下运行程序时gdb
,如果我SIGINT
在 sleep 的中间发送,我可以收集有关主线程的各种信息,例如它的backtrace
和各种寄存器值。
gdb 中是否有一些表达式可以评估是否true
线程必须syscall
在再次在用户空间中执行代码之前越过边界?
理想情况下,会有一个跨平台的解决方案,但特定于平台的解决方案也很有用。
澄清:我不在乎线程是否实际执行;只是它最近的程序计数器值是在内核代码还是用户代码中。
换句话说,能否gdb
告诉我们某个特定线程是否已进入内核但尚未退出内核?
解决方案
如果线程在再次在用户空间中执行代码之前必须跨越系统调用边界,那么 gdb 中是否有某个表达式的计算结果为 true?
可以尝试使用catch syscall nanosleep
,见文档。
catch syscall nanosleep
在 2 个事件上停止:一个在调用系统调用时,一个在从系统调用返回时。您可以使用info breakpoints
来查看此捕获点的命中次数。如果是偶数,那么您应该在用户空间中。如果它很奇怪,那么你应该在内核空间中:
$ gdb -q a.out
Reading symbols from a.out...done.
(gdb) catch syscall nanosleep
Catchpoint 1 (syscall 'nanosleep' [35])
(gdb) i b
Num Type Disp Enb Address What
1 catchpoint keep y syscall "nanosleep"
(gdb) r
Starting program: /home/ks1322/a.out
Missing separate debuginfos, use: dnf debuginfo-install glibc-2.27-8.fc28.x86_64
Catchpoint 1 (call to syscall nanosleep), 0x00007ffff7adeb54 in nanosleep () from /lib64/libc.so.6
(gdb) i b
Num Type Disp Enb Address What
1 catchpoint keep y syscall "nanosleep"
catchpoint already hit 1 time
(gdb) c
Continuing.
Catchpoint 1 (returned from syscall nanosleep), 0x00007ffff7adeb54 in nanosleep () from /lib64/libc.so.6
(gdb) i b
Num Type Disp Enb Address What
1 catchpoint keep y syscall "nanosleep"
catchpoint already hit 2 times
(gdb) c
Continuing.
[Inferior 1 (process 19515) exited normally]
推荐阅读
- jupyter-notebook - sagemath 中的 Jupyter 配置文件
- eclipse - Eclipse 调用层次结构 lambda
- swift - 如何在 TableView 中按 Section 和 Row 搜索?
- c++ - std::hash 的时间复杂度是多少
- android - Google Pay Pass:如何测试会员计划的注册和登录?
- python - 没有名为 PyQt5.sip 的模块
- dax - 为什么表之间的这种 DAX 关系没有按预期聚合?
- c++ - 在 cmd 和 vs 代码中都没有检测到 g++
- node.js - Nest.js 类型“DynamicModule”不可分配给嵌套模块/邮件程序上的“ForwardReference”类型
- django - 在 PythonAnywhere 中添加自定义域不起作用