为什么明确的interrput标志导致C中的分段错误?

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

#include  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");时,我收到了这条消息asm("cli"); 线:

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

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

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

cli是一种特权教育。 它引发#GP(0)exception“如果CPL比当前程序或过程的IOPL更大(具有更少的特权)” 。 这#GP是导致Linux向您的进程提供SIGSEGV的原因。

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

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

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

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


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

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