为什么清除中断标志导致C中的分段故障?

时间:2014-01-06 11:51:02

标签: c assembly x86 interrupt

我正在学习关于Assembly和C.的一些基础知识用于学习目的我决定编写一个禁用Interrupts的简单程序,当用户想要在控制台中键入内容时他/她不能:

#include <stdio.h>
int main(){
    int a;
    printf("enter your number : ");
    asm ("cli");
    scanf("%d", &a);
    printf("your number is %d\n" , a);     
    return 0;
}

但是当我用GCC编译它时,我得到了分段错误:

Segmentation fault (core dumped)

当我使用gdb进行调试时,当程序到达asm("cli");行时,我收到此消息:

Program received signal SIGSEGV, Segmentation fault.
main () at cli.c:6
6       asm ("cli");

2 个答案:

答案 0 :(得分:12)

这种情况正在发生,因为您无法禁用用户空间程序的中断。所有中断都在内核的控制之下。你需要从内核空间做到这一点。在你这样做之前,你需要首先学习内核,然后使用中断非常关键,根据我的知识需要更多的内核知识。

您需要编写一个可以通过/ dev /(或其他)接口与用户空间交互的内核模块。用户空间代码应该请求内核模块禁用中断。

答案 1 :(得分:3)

cli是特权指令。它raises a #GP(0) exception "If the CPL is greater (has less privilege) than the IOPL of the current program or procedure"。这#GP是导致Linux向您的流程提供SIGSEGV的原因。

在Linux下,您可以进行iopl(3)系统调用以提高您的IO私有级别以匹配您的ring 3 CPL,然后您可以禁用来自用户空间的中断。 (但不要这样做,它不支持AFAIK iopl的预期用例是使用来自用户空间的inout指令具有高端口号,而不是cli / sti。x86恰好对两者都使用相同的权限。)

如果您不立即重新启用中断,或者即使您这样做,也可能会导致系统崩溃。或者至少搞砸了多核系统上的CPU。基本上不要这样做,除非您准备按下重置按钮,即关闭X11,保存文件并运行sync。还要将文件系统重新装入只读。

或者在像BOCHS这样的虚拟机或模拟器中尝试它,即使在禁用中断的情况下也可以使用调试器。或者从USB记忆棒启动时尝试。

请注意,禁用中断仅会禁用外部中断。像int $0x80这样的软件生成的中断仍然被采用,但是在禁用中断的情况下进行系统调用可能是一个更糟糕的想法。 (它可能会工作。内核保存/恢复EFLAGS,因此它可能不会在重新启用中断的情况下返回到用户空间。但是,长时间禁用中断对于中断延迟来说是一件坏事。)< / p>

如果您想要作为初学者使用禁用中断,您应该从使用BIOS调用I / O的玩具启动扇区程序中进行操作。或者只是在Linux内核源代码中查看一些禁用/启用中断的地方,如果你很好奇为什么会这样做。

IMO,用户空间中的“正常”asm非常有趣。使用性能计数器,您可以查看CPU如何解码和执行指令的详细信息。有关手册,指南和性能调整信息,请参阅标记wiki中的链接。