User Interrupt
Updated: Sep 21st, 2023
用户态中断(User Interrupt)指的是能够在用户态注册中断处理函数,并且也能够在用户态触发指定的中断处理函数。这种功能可以通过很多种软件机制来实现,并用于进程间通信,在第四代至强 Sapphire Rapids 中,Intel 使用硬件实现了用户态中断,从而基于此实现了极低延迟的进程间通信。
背景:
背景1:硬件中断与 I/O
背景2:进程间通信
在并发编程中,我们常常遇到这样的场景:进程1需要等待进程2完成某事的标志,此时进程1可以选择轮询,也可以选择休眠,等待进程2完成后提醒进程1(类似软件中断)。
轮询需要消耗大量的CPU时间做无用的工作,延时最低,而软件实现的中断机制往往延时较大(依赖调度器的实现),不过由于等待通知的进程可以休眠,相比起轮询可以节省大量的CPU时间。
背景的总结
在计算机系统中实现“通知”这个功能,有很多种方法。
- 硬件实现的中断:只能在内核态触发和处理
- 引入了用户态内核态切换的开销以及内核其他软件栈的负担。
- 延迟最小!也不耗费额外CPU资源
- 软件轮询:可以在用户态触发处理
- 延迟较小
- 浪费大量CPU资源
- 软件实现中断机制:可以在用户态触发处理
- 延迟较大
- 不浪费CPU资源
看起来三种实现都有各自的弊端,没有哪一种是最好的。 但我们不妨想象一下,如果硬件实现的中断可以在用户态触发和处理呢?
硬件实现的用户态中断
在Intel 官方文档中,详细介绍了第四代至强中新增加的 User Interrupts 指令集。另外 Linux 内核开发者也为此开发了一套基础接口,并在LPC2021上进行了相关的演讲。
User Interrupts 指令集包含以下几个指令。
senduipi <uipi_handle>
– send a user IPI to a target task based on the UITT index.
uiret
– Return from a User Interrupt handler
clui
– Mask user interrupts by clearing UIF (User Interrupt Flag).
stui
– Unmask user interrupts by setting UIF.
testui
– Test current value of UIF
#QUESTION : 硬件是如何实现这些用户态中断?
性能表现
Intel 基于 User Interrupt ,在ipc-bench的基础上开发了一个ping-pong IPC benchmark uintr-ipc-bench,并测试了一次ping-pong的延迟。
在下图中展示了用户态中断(User IPI)的延迟表现,该图中仅有一个相对性能。
我运行了简单的几次测试,看起来一般的进程间通信(涉及内核)的方法需要 1~5 us 左右。如果按照上图所示的性能提升,那么这种用户态中断的延迟应该可以降低至几百ns 。
[wyf@cn3 signal]$ ./signal -s 1 -c 1000000
============ RESULTS ================
Message size: 1
Message count: 1000000
Total duration: 3566.216 ms
Average duration: 3.541 us
Minimum duration: 2.304 us
Maximum duration: 79.872 us
Standard deviation: 0.950 us
Message rate: 280409 msg/s
=====================================
[wyf@cn3 pipe]$ ./pipe -s 1 -c 1000000
============ RESULTS ================
Message size: 1
Message count: 1000000
Total duration: 6607.303 ms
Average duration: 6.582 us
Minimum duration: 5.376 us
Maximum duration: 84.224 us
Standard deviation: 0.631 us
Message rate: 151347 msg/s
=====================================
[wyf@cn3 eventfd]$ ./eventfd-bi -c 1000000 -s 1
============ RESULTS ================
Message size: 1
Message count: 1000000
Total duration: 7288.155 ms
Average duration: 7.263 us
Minimum duration: 1.280 us
Maximum duration: 1023.488 us
Standard deviation: 4.361 us
Message rate: 137208 msg/s
=====================================
用处,前景
我认为用户态中断最有用的场景应该是在:对各种高性能的硬件实现用户态的驱动。众所周知,高性能SSD、网卡早已面世,而为了压榨这些硬件的性能,必须要旁路内核,减少内核带来的额外开销。因此,各家厂商的驱动早就已经尝试实现各种优化,如网卡中的RDMA,SSD上的spdk框架,但由于硬件中断必须在内核中处理,因此无论是哪家的硬件都必须在内核中植入一个自己的驱动模块。如今用户态中断的出现,让未来有希望能够完全在用户态实现硬件驱动程序。
更近一步来说,如今Linux内核确实有些臃肿不堪,但其大部分的代码都是各种各种的硬件驱动,若以后硬件驱动可以在用户态中处理,Linux内核的代码规模是不是可以大大削减?是否以后可以让Linux走向更优雅的微内核(或混合内存)?
参考资料
-
User
Interrupts –A faster way to signal
- https://lpc.events/event/11/contributions/985/attachments/756/1417/User_Interrupts_LPC_2021.pdf
- 中断的本质是什么?
- 硬中断
- https://www.phoronix.com/scan.php?page=news_item&px=Linux-RFC-x86-User-Interrupts
- https://software.intel.com/sites/default/files/managed/c5/15/architecture-instruction-set-extensions-programming-reference.pdf
- Linux Support For Sapphire Rapids’ User Interrupts Still Awaiting Mainline - Phoronix