我正在学习关于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");
答案 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
的预期用例是使用来自用户空间的in
和out
指令具有高端口号,而不是cli
/ sti
。x86恰好对两者都使用相同的权限。)
如果您不立即重新启用中断,或者即使您这样做,也可能会导致系统崩溃。或者至少搞砸了多核系统上的CPU。基本上不要这样做,除非您准备按下重置按钮,即关闭X11,保存文件并运行sync
。还要将文件系统重新装入只读。
或者在像BOCHS这样的虚拟机或模拟器中尝试它,即使在禁用中断的情况下也可以使用调试器。或者从USB记忆棒启动时尝试。
请注意,禁用中断仅会禁用外部中断。像int $0x80
这样的软件生成的中断仍然被采用,但是在禁用中断的情况下进行系统调用可能是一个更糟糕的想法。 (它可能会工作。内核保存/恢复EFLAGS,因此它可能不会在重新启用中断的情况下返回到用户空间。但是,长时间禁用中断对于中断延迟来说是一件坏事。)< / p>
如果您想要作为初学者使用禁用中断,您应该从使用BIOS调用I / O的玩具启动扇区程序中进行操作。或者只是在Linux内核源代码中查看一些禁用/启用中断的地方,如果你很好奇为什么会这样做。
IMO,用户空间中的“正常”asm非常有趣。使用性能计数器,您可以查看CPU如何解码和执行指令的详细信息。有关手册,指南和性能调整信息,请参阅x86标记wiki中的链接。