C 是否可以在gdb中确定线程是在内核还是在用户空间中执行(或被阻止)?

C 是否可以在gdb中确定线程是在内核还是在用户空间中执行(或被阻止)?,c,debugging,gdb,kernel,C,Debugging,Gdb,Kernel,考虑以下程序 #include <unistd.h> int main(){ sleep(1000); } 当程序处于休眠状态时,代码正在操作系统内核内执行(可能被阻塞) 当我在>GDB < />代码下运行程序时,如果在睡眠过程中发送 SigNe>代码,我可以收集关于主线程的各种信息,如它的代码>回溯< /COD>和各种登记值。 如果线程在用户空间中再次执行代码之前必须跨越syscall边界,gdb中是否存在计算结果为true的表达式? 理想情况下,会有一个跨平台的解决方

考虑以下程序

#include <unistd.h>

int main(){
    sleep(1000);
}
当程序处于休眠状态时,代码正在操作系统内核内执行(可能被阻塞)

当我在>GDB < />代码下运行程序时,如果在睡眠过程中发送<代码> SigNe>代码,我可以收集关于主线程的各种信息,如它的代码>回溯< /COD>和各种登记值。 如果线程在用户空间中再次执行代码之前必须跨越

syscall
边界,gdb中是否存在计算结果为
true
的表达式?

理想情况下,会有一个跨平台的解决方案,但特定于平台的解决方案也很有用

澄清:我不关心线程是否实际执行;仅限其最新的程序计数器值是否在内核代码或用户代码中

换句话说,
gdb
能否告诉我们某个特定线程是否已经进入内核,但尚未退出内核

如果 在中执行代码之前,线程必须跨越系统调用边界 又是用户空间

您可以尝试使用
catch syscall nanosleep
,请参阅

catch syscall nanosleep
在两个事件上停止:一个在系统调用调用时停止,另一个在系统调用返回时停止。您可以使用
info断点
查看此捕获点的命中次数。如果是偶数,那么您应该在用户空间中。如果是奇数,那么您应该在内核空间中:

$ 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]

你误解了先发制人的多任务工作方式。如果一个“线程”进入睡眠状态,内核在被唤醒之前不会对该线程做任何事情,甚至不会在内部运行任何东西。相反,它会让其他用户空间线程和进程运行。@Someprogrammerdude,我完全知道这一点;这就是为什么我在内核中说“可能被阻塞”。但这与问题是正交的;为了解决这个问题,我考虑了一个在内核中被阻塞(不执行)的线程在内核空间中,并回答当你发送<代码> SigIt<代码>信号时发生的事情,是OS唤醒休眠进程来处理信号,如果进程没有用于
SIGINT
的信号处理程序,操作系统将终止进程。调试器安装特殊的处理程序来捕获所有信号,但它是在用户空间中处理的。@Someprogrammerdude,
SIGINT
仅用于进入调试器,以便我们可以检查状态;我希望它与问题或答案无关,但如果我错了,请纠正我。但这个过程不在“内核空间”。当一个进程进入睡眠状态时,内核会将其放入一个特殊的队列中,等待事件的进程,然后安排另一个进程运行。休眠进程本身不做任何事情,它既不在用户空间也不在内核空间中运行。使用命令可以很容易地看到这一点,该命令将显示非常小的内核时间(“sys”时间)。这仅适用于nanosleep或通用系统调用吗?它适用于任何系统调用(按名称或编号),请参阅文档链接。似乎我必须枚举所有可能的系统调用才能使用它,这有点不幸,但是很高兴知道!您可以
catch syscall
一次在所有系统调用上设置捕捉点。虽然我不知道它对你的最终目标有什么用处。
$ 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]