我尝试停止来自用户空间的特定隔离核心的中断,
所以我设置了 CPU 亲和力:
cpu_set_t set;
CPU_ZERO(&set);
CPU_SET(2, &set);
assert(sched_setaffinity(getpid(),sizeof(set),&set)==0);
并使用
iopl(3)
在用户空间执行特权指令cli/sti
:
iopl(3);
__asm__("cli;");
// busy looping for a while
__asm__("sti;");
还有两个现象我无法解释:
1
cli
实际上不能停止中断(至少不是所有的中断),中断,比如LOC(Local Timer Interrupt)时不时的出来;
我注意到持续的内核补丁阻止了用户空间中的
cli
(reference),但是这个结果可以在内核 4.19.0. 中重现
2 AFAIK,
cli
只清除运行程序的 CPU 的中断标志,但实际上,我的整个系统都卡住了,没有响应我的鼠标或键盘。
(2):Linux 内核的许多部分都依赖于与其他内核的通信,包括依赖于
for each core: run_on(core)
的 RCU 等等。 (https://lwn.net/Articles/262464/)。当这个内核不响应其他内核发送的 IPI 以要求该内核上的内核切换到某个任务,或者可能进行 TLB 击落时,任何执行此操作的内核代码都会卡住。
我不知道究竟是什么事情会导致卡住,但我一点也不觉得奇怪,内核的其他部分正在等待一些依赖于从这个内核上的内核收到的反馈,并且这会阻止将键盘/鼠标事件发送到 X 服务器和用户空间所涉及的某些事情的进展。 (或者甚至到文本控制台?那可能会有更多希望,更少的软件层。)
或者总是有可能一些键盘或鼠标中断被分配到这个核心,并被忽略。
至于 (1):您是否启用了 NMI 看门狗或其他 NMI 来源?这可以使内核在启用(其他?)中断的状态下暂时运行。
我在
kernel/nmi_watchdog = 0
中使用/etc/sysctl.d/99-local.conf
来释放一个额外的性能计数器,但默认是启用的。
(
cli
不会停止不可屏蔽中断,正如您可能从名称中猜到的那样。)
除了那个猜测,我不知道为什么你仍然偶尔会被本地定时器中断;也许更熟悉现代 x86 中断的人会知道。
cli 仅屏蔽可屏蔽中断。本地定时器中断是不可屏蔽的(NMI)。看到这个https://www.tutorialspoint.com/microprocessor/microprocessor_8086_interrupts.htm
你可以试试 linux kernel with tickless operation (CONFIG_NO_HZ_FULL=y) 来减少本地定时器中断的次数到每秒 1 次。看到这个https://docs.kernel.org/timers/no_hz.html