文章目录

  • 未来Eventfd的替代品 User Interrupts
    • 详细介绍什么是 User Interrupts
    • 底层是如何工作的?
      • 内核管理相关的数据结构
      • User IPI
    • 应用接口
    • 具体的例子

未来Eventfd的替代品 User Interrupts

近期,在Linux kernel邮件列表中看到了Intel计划在最新的硬件中支持 User Interrupts功能,并在linux kernel社区中征求意见。邮件中给出了测试的性能数据,如下图:

IPI : inter-processor interrupt (邮件中将User task间的中断称为 User IPI)

进程间通信类型 相对时间(已归一到 User IPI)
User IPI 1.0
Signal 14.8
Eventfd 9.7
Pipe 16.3
Domain 17.3

详细介绍什么是 User Interrupts

用户中断(Uintr)是一种硬件技术,可以将中断直接传递到用户空间。

今天,几乎所有跨越特权界限的交流都是通过内核。 这些包括信号、管道、远程过程调用和基于硬件中断的通知。 User Interrupts提供了一个基础,通过避免通过内核的转换来实现常见的操作,以获得更高的效率(低延迟和低CPU利用率)

在User Interrupts硬件体系结构中,接收者总是被期望用户空间任务( user space task)。 但是,一个User Interrupt 可以由另一个用户空间任务、内核或外部源(如设备)发送

底层是如何工作的?

User Interrupts是一种中断传递机制。中断首先被发送到某个内存位置,然后再被发送到具体的接收者(要求接收者的CPL=3)。

内核管理相关的数据结构

  • UPID : User Posted Interrupt Descriptor — 保持接收者的中断向量信息和通知状态(如正在进行的通知、被抑制通知);

  • UITT : User Interrupt Target Table — 存储UPID指针 和 用于发送端中断路由的向量信息 ;

每个任务的中断状态通过 MSRs 记录,并且在上下文切换期间由内核恢复。

User IPI

senduipi - 根据UITT 索引发送一个 user IPI 到目标task

当 User IPI 发送者执行’senduipi '时,硬件根据UITT和index确定中断发送目标,并将中断向量(63-0)推送到接收者的UPID中。

如果接收端正在运行(CPL=3),发送端cpu将发送一个物理IPI到接收机的cpu。 在接收端,此IPI被检测为用户中断。 调用接收者的用户中断处理程序,并将中断向量(63-0)压栈。

应用接口

User Interrupts (Uintr)是一个可选择的特性(不像信号)。希望使用Uintr的应用程序需要使用与Uintr相关的系统调用来向内核注册自己。Uintr接收器总是一个用户空间任务。一个Uintr sender可以是另一个用户空间任务,内核或设备。

  • 一个接收器可以注册/注销一个中断处理程序使用Uintr接收器相关的系统调用:

    • uintr_register_handler(handler, flags)
    • uintr_unregister_handler(flags)
  • 系统调用还允许接收者注册一个vector 并创建一个用户中断文件描述符 — uintr_fd:
    • uintr_fd = uintr_create_fd(vector, flags)

当eventfd或signal 用于频繁的用户空间事件通知时,Uintr是有用的。uintr_fd的语义有点类似于eventfd()或pipe的写端。

  • 任何发送方都可以使用 uintr_fd 向接收方传递事件(例如,中断)。发送方可以使用uintr_fd 管理与接收者之间的连接:

    • uipi_index = uintr_register_sender(uintr_fd, flags)
  • 在初始设置之后,发送端可以使用 SENDUIPI 指令以及uipi_index 参数来生成 User IPI,而不需要任何内核干预:
    • SENDUIPI <uipi_index>

如果接收端正在运行(CPL=3),则直接交付用户中断,而不需要内核转换。如果接收端没有运行,那么当接收端获得上下文切换回时,中断就会被交付。如果接收者在内核中被阻塞,用户中断被传递到内核,内核然后解除阻塞,向接收者传递中断。

  • 如果发送方是内核或设备,则可以将 uintr_fd 传递给相关的内核实体,以允许它们设置连接,然后生成用于事件传递的 user interrupt。

具体的例子

#define _GNU_SOURCE
#include <syscall.h>
#include <stdio.h>
#include <unistd.h>
#include <x86gprintrin.h>
#include <pthread.h>
#include <stdlib.h>unsigned long uintr_received;
unsigned int uintr_fd;void __attribute__((interrupt))__attribute__((target("general-regs-only", "inline-all-stringops")))
uintr_handler(struct __uintr_frame *ui_frame,unsigned long long vector)
{uintr_received = 1;
}void receiver_setup_interrupt(void)
{int vector = 0;int ret;/* Register interrupt handler */if (uintr_register_handler(uintr_handler, 0)) {printf("[FAIL]\tInterrupt handler register error\n");exit(EXIT_FAILURE);}/* Create uintr_fd */ret = uintr_create_fd(vector, 0);if (ret < 0) {printf("[FAIL]\tInterrupt vector registration error\n");exit(EXIT_FAILURE);}uintr_fd = ret;
}void *sender_thread(void *arg)
{long sleep_usec = (long)arg;int uipi_index;uipi_index = uintr_register_sender(uintr_fd, 0);if (uipi_index < 0) {printf("[FAIL]\tSender register error\n");return NULL;}/* Sleep before sending IPI to allow the receiver to block in the kernel */if (sleep_usec)usleep(sleep_usec);printf("\tother thread: sending IPI\n");_senduipi(uipi_index);uintr_unregister_sender(uintr_fd, 0);return NULL;
}static inline void cpu_relax(void)
{asm volatile("rep; nop" ::: "memory");
}void test_base_ipi(void)
{pthread_t pt;uintr_received = 0;if (pthread_create(&pt, NULL, &sender_thread, NULL)) {printf("[FAIL]\tError creating sender thread\n");return;}printf("[RUN]\tSpin in userspace (waiting for interrupts)\n");// Keep spinning until interrupt receivedwhile (!uintr_received)cpu_relax();printf("[OK]\tUser interrupt received\n");
}void test_blocking_ipi(void)
{pthread_t pt;long sleep_usec;uintr_received = 0;sleep_usec = 1000;if (pthread_create(&pt, NULL, &sender_thread, (void *)sleep_usec)) {printf("[FAIL]\tError creating sender thread\n");return;}printf("[RUN]\tBlock in the kernel (waiting for interrupts)\n");uintr_wait(0);if (uintr_received)printf("[OK]\tUser interrupt received\n");elseprintf("[FAIL]\tUser interrupt not received\n");
}int main(int argc, char *argv[])
{receiver_setup_interrupt();/* Enable interrupts */_stui();test_base_ipi();test_blocking_ipi();close(uintr_fd);uintr_unregister_handler(0);exit(EXIT_SUCCESS);
}

Intel 计划在Linux kernel中引入 User Interrupts,效率是eventfd的10倍相关推荐

  1. Linux Kernel中AEP的现状和发展

    阿里 石洋内核月谈Yesterday AEP简介 AEP是Intel推出的一种新型的非易失Optane Memory设备,又被称作Apache Pass,所以一般习惯称作AEP.在这之前也有类似的设备 ...

  2. linux kernel中的栈的介绍

    目录 1.linux kernel中的中断irq的栈stack (1).arm32体系的irq的栈 (2).arm64体系的irq的栈 2.linux kernel中的栈stack (1).概念介绍: ...

  3. linux kernel中的进程栈

    1.linux中的user mode的进程栈 在thread_info.h中,设置进程栈的大小为16k #define THREAD_SIZE 16384 #define THREAD_START_S ...

  4. Linux kernel 中模块化的平台驱动代码介绍

    介绍 在linux kernel中通过module_platform_driver来实现模块化平台驱动.大量的设备驱动程序都基于该种方式来实现,使用频次非常的高,在linux kernel 5.4.1 ...

  5. Linux kernel中常见的宏整理

    0x00 宏的基本知识 // object-like #define 宏名 替换列表 换行符 //function-like #define 宏名 ([标识符列表]) 替换列表 换行符 替换列表和标识 ...

  6. 内存访问顺序 - part2: 屏障及Linux kernel中屏障的使用

    文章目录 屏障是什么 Linux Kernel 中的屏障 Linux 屏障 API 一般的屏障 强制性屏障 SMP 条件屏障 隐式屏障 其他屏障 屏障的开销 未来的文章 本文翻译自 Memory ac ...

  7. linux内核 漏洞扫描,Linux kernel中存在15年的漏洞

    SCSI 定义了并行I/O 总线和数据协议来连接硬盘驱动.打印机.扫描仪.光驱.测试设备.医疗设备等外部设备到本地计算机.近日,GRIMM在Linux kernel SCSI (Small Compu ...

  8. 关于Linux Kernel中的宏定义likely和unlikely

    在Linux kernel的源代码中,经常能见到if(likely(x))或if(unlikely(x))之类的用法,其确切含义需要说明一下,以便更好的理解kernel的源代码. likely与unl ...

  9. linux kernel中的cmdline的详细介绍

    cmdline 1.向linux kernel添加cmdline的四种方式 (1). 在dts中的bootargs中添加 (2).在BoardConfig中添加 (3).在uboot中添加 (4).在 ...

最新文章

  1. 3D目标检测论文阅读多角度解析
  2. Dubbo源码解析之服务路由策略
  3. ubuntu16.04 ROS安转及RVIZ启动
  4. Handlebars.js 模板引擎
  5. Redis的安装及使用
  6. 强烈推荐|我做系统架构的一些原则
  7. android 字符串对齐,android – 使用Spanable String对齐ImageSpan
  8. 引导页闪屏界面设计灵感
  9. 想通过C++寻找后端开发工作如何提升自己?
  10. Java基础---集合框架---迭代器、ListIterator、Vector中枚举、LinkedList、ArrayList、HashSet、TreeSet、二叉树、Comparator
  11. anaconda 完全卸载——重装
  12. MAX30102 模拟IIC读取程序(C语言)
  13. Mac版的axure原型设计软件
  14. CE修改器学习历程之下载、安装和汉化
  15. 你想要的宏基因组-微生物组知识全在这(19国庆特别篇)
  16. Java编程笔记6:接口
  17. 7-56 福到了 (15 分)
  18. TPC-H和TPC-DS
  19. python游戏开发框架_Python游戏开发:数字华容道
  20. 【CSS】947- 十几个 CSS 高级技巧汇总

热门文章

  1. 编写Makefile:编译当前文件夹以及子文件夹下所有的ccpp文件并生成可执行文件
  2. Win11玩游戏延迟高的解决办法
  3. 程序员锁死服务器搅黄游戏,600万打水漂,创始人负债数百万!
  4. TIM新版支持微信扫码登录:自动生成新QQ
  5. 解密:Gmail移动客户端自动邮件回复技术
  6. 【bzoj2360】【cstc2011】【幸福路径】【倍增+floyd】
  7. 5.2.6UART寄存器编程(下)
  8. 用计算机画对称图形,人教小学美术五下《第17课电脑美术 对称图形》word教案...
  9. 快应用的用法和常见问题解答(上)
  10. 人在江湖,以“核”为贵