假设体系结构是x86。操作系统是基于Linux的。给定单个线程执行int 3指令的多线程进程,中断处理程序是停止执行整个进程还是只停止执行int 3指令的线程?
发布于 2014-03-13 13:43:28
既然这个问题是Linux特有的,那么让我们深入研究内核源代码吧!我们知道int 3会生成一个SIGTRAP,就像我们在do_int3中看到的那样。SIGTRAP的默认行为将终止进程并转储核心。
do_int3调用了do_trap,在经过了大量的间接操作之后,调用了complete_signal,在那里发生了很多神奇的事情。在评论之后,我们可以很清楚地看到正在发生的事情,而不需要太多的解释:
编辑:回答评论:
当进程是ptraced时,手册页中非常详细地记录了这种行为(参见“信号传递-停止”)。基本上,在内核选择了处理信号的任意线程之后,如果选择的线程被跟踪,它进入信号传递-传递-停止-这意味着信号还没有传递到进程,并且可以被跟踪进程抑制。在调试器中是这样的:在调试时,死进程对我们没有任何用处(这不是完全正确的,但让我们考虑一下现场调试场景,这是在这个上下文中唯一有意义的场景),所以默认情况下,我们阻止SIGTRAP,除非用户另有规定。在这种情况下,跟踪的进程如何处理SIGTRAP (SIG_IGN或SIG_DFL或自定义处理程序)与此无关,因为它永远不会知道它发生了什么。
请注意,在SIGTRAP的情况下,跟踪程序进程必须考虑到除要停止的进程之外的各种场景,这一点在手册页中每个ptrace操作下都有详细说明。
发布于 2014-03-13 13:14:20
很容易测试:
#include <thread>
#include <vector>
void f(int v) {
std::this_thread::sleep_for(std::chrono::seconds(2));
if (v == 2) asm("int $3");
std::this_thread::sleep_for(std::chrono::seconds(1));
printf("%d\n", v); // no sync here to keep it simple
}
int main() {
std::vector<std::thread> threads;
for (int i = 0; i < 4; i++) threads.emplace_back(f, i);
for (auto& thread : threads) thread.join();
return 0;
}如果只有线程被停止,它仍然应该打印来自其他线程的消息,但情况并非如此,并且整个进程在打印任何内容之前都会停止(或者在调试时触发断点)。在Ubuntu上,您得到的信息是:
跟踪/断点陷阱(倾弃核)
发布于 2014-03-13 13:49:32
答案其实两者都不是。Int 3用于触发断点。中断处理程序很小,中断和处理程序都不会停止任何线程。
如果没有加载调试器,处理程序要么忽略它,要么调用OS采取某种错误操作,比如发出信号(也许是SIGTRAP)。没有任何线程会受到伤害。
如果存在进程内调试器,则断点ISR将控制传递给它.断点不会停止任何线程,只有中断的线程除外。调试器可能尝试挂起其他。
如果存在进程外调试器,处理程序将调用它,但这必须通过操作系统来进行适当的上下文切换。作为该开关的一部分,操作系统将挂起调试器,这意味着它的所有线程都将停止。
https://stackoverflow.com/questions/22379105
复制相似问题