考虑以下计划。
#include <unistd.h>
int main(){
sleep(1000);
}
如果我们在此程序上运行strace
,则在长时间睡眠之前出现的最后一行如下。
nanosleep({1000, 0},
当程序处于睡眠状态时,代码正在OS内核中执行(可能被阻止)。
当我在gdb
下运行程序时,如果我在睡眠中间发送SIGINT
,我可以收集有关主线程的各种信息,例如backtrace
和各种注册值。
如果在再次在用户空间中执行代码之前线程必须越过true
边界,gdb中是否有某个表达式求值为syscall
?
理想情况下,会有跨平台解决方案,但特定于平台的解决方案也很有用。
澄清:我不关心线程是否实际执行;只是它的最新程序计数器值是在内核代码还是用户代码中。
换句话说,可以gdb
告诉我们某个特定线程是否已进入内核但尚未退出内核?
答案 0 :(得分:1)
gdb中是否有一些表达式,如果是,则计算结果为true 线程必须在执行代码之前跨越系统调用边界 用户空间再次?
您可以尝试使用catch syscall nanosleep
,请参阅documentation。
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]