Linux内核中断机制

news2024/11/26 14:31:36

什么是中断?

中断是一种打断程序的正常执行流程的事件,这种事件以电信号的形式出现,可以由硬件设备或者CPU本身生成。

在中断发生后,正常的执行流被立即中止,转而执行中断处理程序(handler)。中断处理完成之后,先前的执行流将继续。

对中断进行分类:

同步的中断(exception),下文均称其为异常:由CPU自己在执行指令时生成(比如除以0或者系统调用。因为执行指令总是要依照系统时钟,所以叫它同步中断);
异步的中断(interrupt):由外部事件生成(比如敲键盘)。

可以屏蔽的中断:可以被CPU忽略,需要接到INT引脚。
不能屏蔽的中断:需要接到NMI引脚。

大多数的中断是可以屏蔽掉的。可以通过屏蔽中断电信号阻止相关中断的处理,直到我们放行中断信号。

异常

有两种原因可以导致异常:

  1. 处理器检测到的:比如fault(除0、缺页)、debug trap等
  2. 生成的:int n,这是一条汇编指令,功能是引发中断过程,从此处转去执行序号为n的处理程序。

fault可以在特定指令执行前就被触发(比如缺页),可以被纠正(比如换页)。EIP寄存器会存储对应的指令。于是在处理完异常之后可以继续执行。

trap是在指令执行后触发的异常。同样地,EIP寄存器会存储对应的指令。

一些硬件概念

可编程中断控制器(Programmable Interrupt Controller)

在这里插入图片描述
比如上图,不可屏蔽的中断走NMI引脚,可屏蔽的中断走INTR引脚。

能产生中断的设备有一个输出引脚,用来生成中断请求(Interrupt ReQuest, IRQ)。我们把这个引脚叫做IRQ引脚。设备的引脚接到可编程中断控制器(PIC)上,PIC和CPU的INTR引脚相连。

此外,PIC也有其他和CPU相连的(硬件)接口,用来交换信息。

设备产生中断的流程如下:

  1. 设备在对应的IRQ线(中断线)上生成一个中断。
  2. PIC将IRQ转换成一个向量号,把这个向量号写到硬件接口上,用来给CPU读。
  3. PIC在INTR线上生成一个中断。
  4. 在生成另外一个中断之前,PIC等待CPU确认当前这个中断。
  5. CPU确认并处理当前中断。

由此可见,根据PIC的设计,在CPU确认当前中断之前,PIC没法再开新的中断。

注意:CPU确认了当前中断和完成中断处理是两个概念。当CPU确认了一个中断后,PIC可以请求另一个中断。这意味着中断控制器可以在CPU还没有处理完前一个中断时请求新的中断。至于会不会出现嵌套中断,这取决于OS的管理方式。

PIC允许每一条IRQ线都被单独地开启或者禁用。

对称多处理器(Symmetric Multi Processor, SMP)系统中的中断控制器

SMP:其实可以理解为多核处理器。这些个核共享系统的所有资源(内存,总线,外设etc)

由于SMP有多个核,所以可能有多个中断控制器。比如,在x86架构中:

在这里插入图片描述
每个核都有局部的Advanced PIC,用来接收局部设备的IRQ(比如温度传感或者计时器)。同时,存在一个IO外设,用来向这些CPU核分发IO设备的异常。

中断的控制

一般来说,为了确保 中断处理函数 和 其他并行操作 之间访问数据的同步性,很多时候会需要启用/禁用某个中断线上的中断。有多种实现方式:

  1. 在设备级别,通常涉及对设备的控制寄存器或寄存器组进行编程。一般由OS调用设备驱动完成。
  2. 在PIC级别,可以通过禁用IRQ实现。
  3. 在CPU级别,可以用cli(CLear Interrupt)指令或者sti(SeT Interrupt)指令实现禁用中断或者开启中断。

中断的优先级

大多数的体系结构都支持中断优先级。一旦启用中断优先级,那么在一个中断执行过程中,有且仅有更高优先级的中断可以打断它。

在这里插入图片描述

并不是所有的体系结构都支持中断优先级。
为通用OS定义一般性的中断优先级也比较困难。
有的系统内核不用中断优先级。
RTOS一般都会用中断优先级。

x86平台的中断处理

中断描述符表(Interrupt Descriptor Table, IDT)

中断描述符表(IDT)把中断或者异常的标识和处理相关事件的指令描述符相关联(可以理解为以特殊形式存在的回调)。

标识符称为向量号,相关的指令称为异常处理程序。

IDT的特征如下:

  1. 在给定向量号被触发时,IDT被CPU用作为跳表。
  2. IDT大小为256*8字节。
  3. 可能在物理地址的任何地方(由于虚拟内存映射)。
  4. CPU中有IDTR寄存器,用于存放IDT的基地址和表长度值。

在这里插入图片描述
这个图是IDT表。0-31项存放异常,32-127项存放设备中断,128用于系统调用,其他项的用来存放别的中断。

每一个数字代表一个表项。如下图,是一个表项中包含的中断的详细信息:

在这里插入图片描述

  1. segment selector:找出中断处理程序的代码段
  2. offset:在代码段中的偏移
  3. T:gate的类型
  4. DPL:使用段中内容需要的最小权限

其中,在x86机器上,一个IDT项有8字节,这个IDT项被称为gate。一共有三种gate:

  1. interrupt gate:此时IDT项中有中断/异常处理程序的地址。在跳转到对应的异常处理代码时,会屏蔽掉所有可屏蔽的中断。 x86 架构中的 EFLAGS 寄存器中有一个标志位叫做 “Interrupt Flag”(IF)标志位,这个标志位用来控制中断的开关,具体来说:当 IF 标志位被设置为 1 时,表示中断允许响应,当 IF 标志位被设置为 0 时,表示中断被禁用。当跳转到一个中断或异常处理程序时,一般会在进入处理程序之前禁用中断,也就是将 IF 标志位设置为 0。这是为了确保在处理当前中断或异常时不会被其他中断打断,从而保证了中断处理程序的执行的完整性和稳定性。在执行完中断或异常处理程序后,通常会根据需要重新启用中断,将 IF 标志位设置回 1,以便允许系统响应其他中断请求。
  2. trap gate:和interrupt gate类似,但是在跳转时不会屏蔽中断。
  3. task gate(linux中不用)

中断处理函数的地址

寻址过程如下图:

在这里插入图片描述
我们要找中断处理函数的地址:

首先基于IDT项中的segment selector找到GDT/LDT里对应的段描述符,基于段描述符里的基地址和IDT项中的偏移量,就可以找到对应的中断处理函数的起始地址。

中断处理函数的栈

正常函数的控制流转换,以函数调用为例,基于栈。中断处理函数也是基于栈的。用栈来存放调用中断处理函数之前的执行上下文。

如下图,中断首先保存EFLAGS寄存器内容,然后保存当前被打断的进程的上下文。有的异常也会在栈上保存错误码。

在这里插入图片描述

处理到来的IRQ

在生成中断请求IRQ之后,CPU要执行一系列准备工作,最终执行内核中的中断处理函数:

  • CPU查看特权级
  • 如果需要更改特权级,那么
    • 把栈换成新特权级的栈
    • 把老栈的信息存放在新栈上
  • 在栈上存放EFALGS、CS、EIP寄存器
  • 在栈上存放error code
  • 执行内核中的中断处理函数

从中断处理函数中返回

大多数体系结构会提供特殊指令,允许清空栈上中断处理的相关内容并且恢复之前的执行。

比如,x86上有IRET指令,负责从中断处理中恢复。

在执行完中断处理函数之后:

  • 弹出error code
  • 执行IRET指令(如果特权级别发生改变,那么恢复特权级别)

Linux中的中断处理

Linux中断处理的三个阶段:critical(关键阶段)、immediate(即时阶段)和deferred(延迟阶段)。

基本上是确认——即时处理——延时处理三个步骤

在第一个阶段,内核会进行通用的中断处理,确定中断号、中断处理函数和对应的中断控制器。内核和中断控制器进行交互,在中断控制器层面确认中断的到来。以确保中断不会被误报或丢失。此阶段,内核通常会禁用本地CPU的中断,以确保在中断处理的关键阶段中不会被其他中断打断。

在第二个阶段,所有和这个中断相关的设备驱动的处理函数都会被调用(有的设备驱动的处理函数发现这个中断不是自己生成的,那么它就会直接退出)。调用完成之后,中断控制器的end of interrupt方法被调用,直到此时,本地CPU的中断才会被启用,允许别的中断到来。

一个中断号可能对应多个设备,此时,中断被共享。这个时候,每个设备就要自己确认是不是自己生成了这个中断。

最后一个阶段,延迟工作部分,就是常说的中断处理的下半部分工作。此时,本地CPU启用中断。

在这里插入图片描述

嵌套的中断和异常

由于各种爆栈问题的复杂处理方式(比如允许一级嵌套、多级嵌套、加大内核栈深度等),中断嵌套目前已经被linux禁用了。有利于内核的维护。

但是,这不意味着中断和异常之间的嵌套不复存在。

中断和异常嵌套的一些原则,如下图所示:

  • 异常不能抢占中断
  • 中断可以抢占异常
  • 一个中断不能抢占另一个中断

在这里插入图片描述

中断上下文

定义:在中断被处理时(从 CPU跳转到中断处理函数 到 中断处理函数返回,即IRET指令执行 的这段时间)被称为中断上下文。

在这段时间里运行的代码有下列性质:

  • 运行在这段代码中,是因为有IRQ而不是有异常
  • 这段代码没有相关联的进程上下文
  • 不能做上下文切换(比如sleep,调度,访问用户内存)

处理中断时可以被延迟的操作(deferrable action)

可延迟操作用于在稍后的时间运行钩子函数。这些钩子函数通常用于执行与中断处理相关的任务或执行需要延迟执行的操作。

可延迟操作可以分为两个大类:在中断上下文中运行的,在进程上下文中运行的。

  • 在中断上下文中运行的:用于避免在中断处理程序函数中执行过多的工作。在中断处理期间会禁用其他中断,如果中断处理程序运行时间过长,会降低系统性能。比如,可能会因为无法及时处理网络数据包而导致丢包。

使用中断上下文的可延迟操作的主要目的是确保中断处理程序尽可能快速地执行,以减小系统响应时间并减少中断处理程序的持续时间。通过将某些任务推迟到稍后在进程上下文中执行,可以避免中断处理程序的过度运行,从而提高系统性能。

可延迟操作有相应的API,包括初始化、激活、调度、启用/禁用(用于上下文信息同步)等。

一般来说,设备驱动会在初始化设备实例时初始化可延迟操作的相关信息,在中断处理函数里进行可延迟操作的激活和调度。

软中断

在中断处理函数中启动可延迟操作,但是可延迟操作仍然在中断上下文中运行。软中断是一种允许在中断处理程序中排队和异步执行工作的方式,

API:

初始化: open_softirq()
激活: raise_softirq()
启用禁用: local_bh_disable(), local_bh_enable()

一旦激活,则钩子函数do_softirq() 可以在中断处理函数之后运行,也可以在ksoftirqd内核线程里运行。

因为软中断可以调度它们自己,比如触发了新的软中断,也可以被别的中断调度,所以有可能会导致软中断的饥饿。目前,linux内核里设置了

  • 软中断处理的最大允许时间MAX_SOFTIRQ_TIME 。如果软中断在执行时超过了这个时间限制,它会被中断,以确保系统能够处理其他重要的中断事件,避免过长的中断响应时间。
  • 软中断的最大调度次数MAX_SOFTIRQ_RESTART 。这是指允许软中断在连续执行多少次后重新排队或重调度。如果软中断连续执行次数超过了这个限制,它会被重新排队,以允许其他中断事件得到处理。

一旦上述限制条件触发,内核线程ksoftirqd 就会出马,把所有挂起的软中断全执行掉。

软中断一般被严格限制使用,只有少数需要低延迟高频性能的子系统会用软中断:

/* PLEASE, avoid to allocate new softirqs, if you need not _really_ high
   frequency threaded job scheduling. For almost all the purposes
   tasklets are more than enough. F.e. all serial device BHs et
   al. should be converted to tasklets, not to softirqs.
*/

enum
{
  HI_SOFTIRQ=0,
  TIMER_SOFTIRQ,
  NET_TX_SOFTIRQ,
  NET_RX_SOFTIRQ,
  BLOCK_SOFTIRQ,
  IRQ_POLL_SOFTIRQ,
  TASKLET_SOFTIRQ,
  SCHED_SOFTIRQ,
  HRTIMER_SOFTIRQ,
  RCU_SOFTIRQ,    /* Preferable RCU should always be the last softirq */

  NR_SOFTIRQS
};

chatGPT说,Tasklet 是软中断的一种特殊情况,用于执行快速的、低延迟的任务,而软中断是一种更通用的机制,可以用于执行各种类型的任务,包括相对复杂的操作。选择使用哪种机制取决于任务的复杂性和性能要求。

在Linux内核中,不同的软中断执行过程通常会共享相同的内核栈,而不是为每个软中断分配单独的栈空间。这是因为内核需要高效管理栈资源,分配单独的栈空间给每个软中断会占用大量的内存,并且会引入复杂性。共享栈的方法可以有效节省内存,并且已经在内核中实现。

软中断通常不会被定时器中断打断和重新调度。软中断在内核中运行于中断上下文,具有较高的优先级,因此它们通常不会被其他中断事件打断,除非发生了一些特殊情况。定时器中断(timer interrupt)通常以较低的优先级运行,用于触发定时器处理、调度延迟工作队列等任务。因此,定时器中断一般不会在执行软中断时打断软中断的执行,除非内核开启抢占模式,允许中断的抢占。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1014697.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

IT运维:使用数据分析平台监控Windows Eventlog

TIPS:本文鸿鹄版本:2.10.0及以上版本 概述 本文基于《IT运维:利用鸿鹄采集Windows event log数据》(以下简称原文)文章进行了细化与延伸。主要包括细化了安装步骤,增加了仪表板。 鸿鹄端配置 创建数据集与数…

[Linux入门]---搭建Linux环境

1.Linux环境的搭建方式 使用Linux操作系统的三种途径: 1.直接安装在物理机上,但是由于 Linux 桌面使用起来非常不友好,不推荐。 2.使用虚拟机软件,将 Linux 搭建在虚拟机上,但是由于当前的虚拟机软件(如 VMWare 之类的…

科研生产力:Zotero

目录 Zotero安装配置Zotero常用插件1. Zotero Connector2. Jasminum-茉莉花插件3. Zotero-scihub4. Zotero-pdf-translate5. Zotero-if6. Zotero-style7. Zotero-tag8. ZotFile9. zotero-better-notesZotero GPT 一些学习资源 Zotero安装配置 进入Zotero官网:https:…

前端用户体验设计:创造卓越的用户界面和交互

💂 个人网站:【工具大全】【游戏大全】【神级源码资源网】🤟 前端学习课程:👉【28个案例趣学前端】【400个JS面试题】💅 寻找学习交流、摸鱼划水的小伙伴,请点击【摸鱼学习交流群】 用户体验(Us…

Softek Barcode Reader Toolkit 9.3 Crack

现在使用 Pdfium 读取 PDF 文件并改进了对 QRCode、PDF417 和 Code 39 的支持。 2023 年 9 月 11 日 - 16:32新版本 特征 现在使用 Pdfium 读取 PDF 文件。 提高了 GetBarStringPos 返回值的准确性。 如果 PDF417 条形码包含超过数据字节计数的符号长度描述符,则它会…

透视俄乌网络战之二:Conti勒索软件集团(下)

透视俄乌网络战之一:数据擦除软件 透视俄乌网络战之二:Conti勒索软件集团(上) Conti勒索软件集团(下) 1. 管理面板源代码2. Pony凭证窃取恶意软件3. TTPs4. Conti Locker v2源代码5. Conti团伙培训材料6. T…

SAP 信息类型:使用 PA30,PA20 创建,更改,复制,删除,概览

目录 创建信息类型 显示信息类型 更改信息类型 复制信息类型 删除信息类型 显示信息类型概述 创建信息类型 步骤 1)在 SAP 命令提示符下,输入事务 PA30 步骤 2)在下一个 SAP 屏幕中, 输入人员编号点击输入按钮 选择相关的…

SaaS软件能保证数据安全吗?

SaaS软件能保证数据安全吗? 本文将要尝试从各个方面尽可能客观的去阐述这个问题,而不是简单自嗨式的说简道云平台如何保障数据安全。 建议先收藏起来慢慢品! 01 SaaS安全到底是什么?——定义解读 本文所用SaaS平台>>>…

VR航天航空巡展VR科技馆航天主题科普设备沉浸遨游太空

每当飞机飞过头顶,我们总是忍不住抬头去仰望。从嫦娥奔月的神话传说,到莱特兄弟实现了上天翱翔的梦想,人类一直在不断探索更辽阔的天空和浩瀚的宇宙。 航空科普 寻梦而行 普乐蛙VR航天航空巡展,正在湖南郴州如火如荼的进行中&…

el-dialog窗口添加滚动条

0 效果 1 代码 /deep/.addMicroDialog {height: 700px !important;overflow-y: scroll;}/deep/.addMicroDialog:hover::-webkit-scrollbar-thumb {background: #9cbaff;border-radius: 10px;}/deep/.addMicroDialog::-webkit-scrollbar {width: 6px;height: 0px;}

R--基础知识总结

R程序包的安装和加载 install.packageS(TSA) library(TSA) R向量 (vector) 数值向量 1.赋值 x<-c(1,2,3,4)assign( x,c(1,2,3,4))xc(1,2,3,4)x<-2*1:15 % x(2,4,...,30) 等差运算优先于乘法运算seq(fromvalue1,tovalue2,byvalue3) seq(length…

golang iris框架 + linux后端运行

go mod init myappgo get github.com/kataras/iris/v12latestpackage mainimport "github.com/kataras/iris/v12"func main(){app : iris.New()app.Listen(":port") }打包应用 go build main.go开启服务 #nohup ./程序名称 nohup ./main关闭后台 #ps -e…

国际版阿里云/腾讯云免费:阿里云产品-弹性核算简介(依据官网转载)

阿里云产品-弹性核算简介(依据官网转载) 云服务器ECS&#xff08;Elastic Compute Service&#xff09;是阿里云供给的功能杰出、安稳牢靠、弹性扩展的IaaS&#xff08;Infrastructure as a Service&#xff09;等级云核算服务。 实例&#xff1a;等同于一台虚拟服务器&#xf…

vscode如何设置文件折叠

随着项目的不断迭代开发&#xff0c;复杂度越来越高&#xff0c;配置文件越来越多&#xff0c;导致vscode左侧文件列表展示非常不直观&#xff0c;幸好可以通过文件折叠来简化展示效果&#xff0c;把同类相关的文件折叠在一块展示&#xff0c;方便查看配置文件。配置好后的效果…

C++之vector迭代器函数begin、end、rebegin、rend、cbegin、cend、crbegin、crend总结(二百零一)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

视频监控管理平台/视频汇聚/视频云存储EasyCVR安全检查的相关问题及解决方法3.0

智能视频监控系统/视频云存储/集中存储/视频汇聚平台EasyCVR具备视频融合汇聚能力&#xff0c;作为安防视频监控综合管理平台&#xff0c;它支持多协议接入、多格式视频流分发&#xff0c;视频监控综合管理平台EasyCVR支持海量视频汇聚管理&#xff0c;可应用在多样化的场景上&…

Weblogic SSRF漏洞

Weblogic SSRF漏洞 1.环境搭建 http://10.9.75.198:7001/uddiexplorer/2.漏洞复现 SSRF漏洞存在于http://10.9.75.198:7001/uddiexplorer/SearchPublicRegistries.jsp2.1bp抓包&#xff0c;测试该漏洞。通过测试端口&#xff0c;查看哪个端口能够进行具体得操作 可访问的端…

虚拟机作为master远程控制台式机中的机器人在仿真环境中进行slam地图构建与自主导航

文章目录 前言一、思路流程二、具体步骤1.虚拟机网络配置2.台式机网络配置3.网络测试 三、远程操控SLAM建立地图三、远程操控SLAM导航 前言 虚拟机作为master远程控制台式机中的机器人在仿真环境中进行slam地图构建与自主导航 最近有时间一直在搞Ubuntu虚拟机与台式机的通讯&…

承载22倍于自身重量前行,垂直跳跃59厘米,用爆炸驱动的昆虫机器人来了

这款机器人由来自康奈尔大学的研究者研发&#xff0c;该机器人长 29 毫米&#xff0c;重量仅为 1.6 克&#xff0c;可以垂直跳跃 59 厘米&#xff0c;并且可以携带 22 倍&#xff08;36 克&#xff09;于自身重量的物品行走。 小小机器人能量大爆发&#xff0c;身体如昆虫一般大…

企业架构LNMP学习笔记46

PHP测试连接代码&#xff1a; php代码测试使用memcached&#xff1a; 示例代码&#xff1a; <?php //实例化类 $mem new memcached(); //调用连接memcached方法 注意连接地址和端口号 $mem->addServer(192.168.17.114,11211); //存数据 var_dump($mem->set(name,l…