1.沁恒 RISC-V 单片机 CH32V203C8T6 只响应一次中断
2.鸿蒙轻内核M核源码分析:中断Hwi
3.android 为ä»ä¹ä¸å»ºè®®ä½¿ç¨Thread.stop
4.读懂isInterrupted、源码interrupted和interrupt
5.中断入口从哪个文件中可以找到
6.Linux 中断( IRQ / softirq )基础:原理及内核实现
沁恒 RISC-V 单片机 CH32V203C8T6 只响应一次中断
遇到的源码问题是关于沁恒 RISC-V 单片机 CHVC8T6 的中断管理。PB5引脚上配置有一个按键,源码常态下其电平为低,源码按下时变为高电平。源码在此环境中,源码MGS源码中断响应机制存在一个特定的源码限制:中断函数能够被触发并执行,但似乎只能响应一次,源码后续按键动作将无法再次引发中断。源码
为解决这一问题,源码关键在于对中断处理程序的源码适当修改。在中断函数所在的源码源代码文件中,可以尝试添加额外的源码代码来解决单次响应的限制。具体的源码实现方法可能包括在中断服务处理结束后,手动清零中断标志或者通过软件方式阻止中断再次触发,源码确保在第一次响应后,该按键的行为可以被程序重新控制。这通常涉及检查中断标志并采取适当的复位措施,以防止进入死循环或错过后续的中断请求。
以下是可能的修改示例(注意,这只是一个示例,实际代码可能需要根据具体硬件和中断控制器的文档进行调整):
void interrupt_handler() {
// 处理中断逻辑...
// 检查中断标志并复位(如果需要)
if (中断标志) {
中断标志 = 0; // 或者使用适当的硬件API复位中断标志
}
// 防止后续中断立即触发(如果必要)
disable_next_interrupt();
// 函数结束,中断处理完成
}
请确保在实际应用中,根据芯片文档和中断控制器的特性来调整上述代码,以确保中断响应的正确性和可靠性。
鸿蒙轻内核M核源码分析:中断Hwi
在鸿蒙轻内核源码分析系列中,本文将深入探讨中断模块,旨在帮助读者理解中断相关概念、鸿蒙轻内核中断模块的源代码实现。本文所涉及源码基于OpenHarmony LiteOS-M内核,读者可通过开源站点 gitee.com/openharmony/k... 获取。kuaidial 源码中断概念介绍
中断机制允许CPU在特定事件发生时暂停当前执行的任务,转而处理该事件。这些事件通常由外部设备触发,通过中断信号通知CPU。中断涉及硬件设备、中断控制器和CPU三部分:设备产生中断信号;中断控制器接收信号并发出中断请求给CPU;CPU响应中断,执行中断处理程序。中断相关的硬件介绍
硬件层面,中断源分为设备、中断控制器和CPU。设备产生中断信号;中断控制器接收并转发这些信号至CPU;CPU在接收到中断请求后,暂停当前任务,转而执行中断处理程序。中断相关的概念
每个中断信号都附带中断号,用于识别中断源。中断优先级根据事件的重要性和紧迫性进行划分。当设备触发中断后,CPU中断当前任务,执行中断处理程序。中断处理程序由设备特定,且通常以中断向量表中的地址作为入口点。中断向量表按中断号排序,存储中断处理程序的地址。鸿蒙轻内核中断源代码
中断相关的声明和定义
在文件 kernel\arch\arm\cortex-m7\gcc\los_interrupt.c 中定义了结构体、全局变量和内联函数。关键变量 g_intCount 记录当前正在处理的中断数量,内联函数 HalIsIntActive() 用于检查是否正在处理中断。中断向量表在中断初始化过程中设置,用于映射中断号到相应的中断处理程序。中断初始化 HalHwiInit()
系统启动时,ollyice 源码在 kernel\src\los_init.c 中初始化中断。HalHwiInit() 函数在 kernel\arch\arm\cortex-m7\gcc\los_interrupt.c 中实现,负责设置中断向量表和优先级组,配置中断源,如系统中断和定时器中断。创建中断 HalHwiCreate()
开发者可通过 HalHwiCreate() 函数注册中断处理程序,传入中断号、优先级和中断模式。函数内部验证参数,设置中断处理程序,最终通过调用 CMSIS 函数完成中断创建。删除中断 HalHwiDelete()
中断删除操作通过 HalHwiDelete() 实现,接收中断号作为参数,调用 CMSIS 函数失能中断,设置默认中断处理程序,完成中断删除。中断处理执行入口程序
默认的中断处理程序 HalHwiDefaultHandler() 仅用于打印中断号后进行死循环。HalInterrupt() 是中断处理执行入口程序的核心,它包含中断数量计数、中断号获取、中断前后的操作以及调用中断处理程序的逻辑。开关中断
开关中断用于控制CPU是否响应外部中断。通过宏 LOS_IntLock() 关闭中断, LOS_IntRestore() 恢复中断状态, LOS_IntUnLock() 使能中断。这组宏对应汇编函数,使用寄存器 PRIMASK 控制中断状态。小结
本文详细解析了鸿蒙轻内核中断模块的源代码,涵盖了中断概念、初始化、libreadline 源码创建、删除以及开关操作。后续文章将带来更多深入技术分享。欢迎在 gitee.com/openharmony/k... 分享学习心得、提出问题或建议。关注、点赞、Star 和 Fork 到个人账户,便于获取更多资源。android 为ä»ä¹ä¸å»ºè®®ä½¿ç¨Thread.stop
å½è°ç¨Thread.stop()æ¹æ³æ¶ï¼ä¼åç以ä¸ä¸¤ç§äºæ ï¼
1. å³å¯æåºThreadDeathå¼å¸¸ï¼å¨çº¿ç¨çrun()æ¹æ³éé¢ï¼ä»»ä½ä¸å»é½å¯è½æåºThreadDeath Errorï¼å æ¬å¨catchæè finallyè¯å¥ä¸ã
2. éæ¾è¯¥çº¿ç¨çææéã
å½çº¿ç¨æåºThreadDeathå¼å¸¸æ¶ï¼ä¼å¯¼è´çº¿ç¨çrun()æ¹æ³çªç¶è¿åæ¥è¾¾å°åæ¢è¯¥çº¿ç¨çç®çãè¿ä¸ªå¼å¸¸å¯ä»¥å¨è¯¥çº¿ç¨run()ä»»æä¸ä¸ªæ§è¡ç¹æåºãååä¸åªè¦ä¸è°ç¨thread.stop()æ¹æ³ï¼çº¿ç¨ä¼ç«å³åæ¢ï¼å¹¶æåºThreadDeath errorï¼æ¥çäºThreadçæºä»£ç åæåç°ï¼åå Thread.stop0()æ¹æ³æ¯åæ¥çï¼èæ们工ä½çº¿ç¨çrun()æ¹æ³ä¹æ¯åæ¥ï¼é£ä¹è¿æ ·ä¼å¯¼è´ä¸»çº¿ç¨åå·¥ä½çº¿ç¨å ±åäºç¨åä¸ä¸ªéï¼å·¥ä½çº¿ç¨å¯¹è±¡æ¬èº«ï¼ï¼ç±äºå·¥ä½çº¿ç¨å¨å¯å¨åå°±å è·å¾äºéï¼æ以æ 论å¦ä½ï¼å½ä¸»çº¿ç¨å¨è°ç¨thread.stop()æ¶ï¼å®å¿ é¡»è¦çå°å·¥ä½çº¿ç¨çrun()æ¹æ³æ§è¡ç»æåæè½è¿è¡ã
å æ¤ï¼thread.stop()æ¯ä¸å®å ¨çï¼ä¸»è¦é对äºäºï¼éæ¾æ¹çº¿ç¨æææçææçéï¼èéççªç¶éæ¾ä¼å¯¼è´è¢«ä¿æ¤çæ°æ®çä¸ä¸è´æ§ã
æ£ç¡®åæ¢çº¿ç¨æ»ç»èµ·æ¥æ¯ä»¥ä¸ä¸ç¹ï¼
1. 使ç¨violate boolean åéæ¥è¡¨ç¤ºçº¿ç¨æ¯å¦åæ¢ï¼
2. åæ¢çº¿ç¨æ¶ï¼éè¦è°ç¨åæ¢çº¿ç¨çinterrupt()æ¹æ³ï¼å 为线ç¨æå¯è½å¨wait()æè sleep()ï¼æé«åæ¢çº¿ç¨çåæ¶æ§ï¼
3. 对äºblocking IOçå¤çï¼å°½é使ç¨interruptibleChannelæ¥ä»£æ¿ blocking IOã
读懂isInterrupted、interrupted和interrupt
本文主要介绍了Java中isInterrupted(), interrupted()和interrupt()这三个方法的用途。isInterrupted()用于检查当前线程是否有中断标志,interrupted()则不仅检查还清除该标志,而interrupt()则是给线程设置中断标志,线程继续运行。当线程在wait、join或sleep时,若被中断,会引发InterruptedException。
在JDK1.8版本的源码中,isInterrupted()是实例方法,检查标志但不清除;interrupted()是静态方法,针对当前线程,检查并清除标志;interrupt()是实例方法,直接设置中断标志。下面通过代码示例来展示这些操作的效果。
当线程t1被中断后,调用wait方法,控制台输出显示中断状态和InterruptedException的触发。如果在调用wait前先用Thread.interrupted()清除中断标记,rbtools源码那么即使线程中断,wait方法也不会再抛出异常。
总结来说,理解这三个方法对于处理线程中断和异常至关重要,特别是在处理同步操作时,正确使用它们能帮助你避免不必要的中断异常。
中断入口从哪个文件中可以找到
中断入口通常可以在操作系统的中断描述符表(Interrupt Descriptor Table,简称IDT)或者相应的中断处理代码中找到,但这并不直接对应于某个具体的“文件”,因为它涉及到的是底层系统架构和内核级别的实现。不过,如果我们从源代码的角度去看,中断处理的相关代码通常会在操作系统的内核源代码中找到。
详细来说,中断入口是操作系统响应硬件中断或软件异常时执行的代码的起始点。在x架构的计算机系统中,IDT是一个用于存储中断处理函数地址的数据结构,操作系统在初始化阶段会设置好这个表,并在运行时根据中断类型查找对应的处理函数。
例如,在Linux操作系统中,与中断处理相关的代码可以在内核源代码的arch/x/kernel/目录下的irq.c、apic.c等文件中找到。这些文件中定义了中断请求(IRQ)的处理流程、中断控制器的初始化等。对于软件异常,如除零错误、页面错误等,其处理代码通常位于内核源代码的其他部分,如entry.S(汇编代码文件)或traps.c等。
另外,设备驱动程序中也会包含与特定设备相关的中断处理代码。当设备产生中断时,操作系统会调用这些驱动程序中的中断处理函数。
因此,要找到中断入口的具体位置,需要查阅操作系统的内核源代码,并根据操作系统的类型、版本以及目标硬件平台的不同,在相应的文件中进行查找。同时,还需要对操作系统的中断处理机制有一定的了解,以便能够准确地定位到中断入口的代码。
Linux 中断( IRQ / softirq )基础:原理及内核实现
中断(IRQ),尤其是软中断(softirq)的广泛用途之一是网络数据包的接收与发送,但其应用场景并非单一。本文将全面整理中断(IRQ)与软中断(softirq)的基础知识,这些内容与网络数据包处理虽无直接联系,但整理本文旨在更深入地理解网络数据包处理机制。
什么是中断?
CPU 通过时分复用处理多任务,其中包括硬件任务,如磁盘读写、键盘输入,以及软件任务,如网络数据包处理。CPU 在任何时刻只能执行一个任务。当某个硬件或软件任务当前未被执行,但希望CPU立即处理时,会向CPU发送中断请求——希望CPU暂停手头工作,优先服务“我”。中断以事件形式通知CPU,因此常看到“在XX条件下会触发XX中断事件”的表述。
中断分为两类:
管理中断的设备:Advanced Programmable Interrupt Controller(APIC)。
硬中断的中断处理流程
中断随时发生,处理流程如下:
Maskable and non-maskable
Maskable interrupts 在x_上可以通过sti/cli指令来屏蔽(关闭)和恢复:
在屏蔽期间,这种类型的中断不会触发新的中断事件。大部分IRQ都属于这种类型。例如,网卡的收发包硬件中断。
Non-maskable interrupts 不可屏蔽,因此属于更高优先级的类型。
问题:执行速度与逻辑复杂性之间的矛盾
IRQ处理器的两个特点如下:
存在内在矛盾。
解决方式:中断的推迟处理(deferred interrupt handling)
传统解决方式是将中断处理分为两部分:
这种方式称为中断的推迟处理或延后处理。现在已是一个通用术语,涵盖各种推迟执行中断处理的方式。中断分为两部分处理:
在Linux中,有三种推迟中断(deferred interrupts):
具体细节将在后续介绍。
软中断与软中断子系统
软中断是内核子系统的一部分:
每个CPU上会初始化一个ksoftirqd内核线程,负责处理各种类型的softirq中断事件;
使用cgroup ls或ps -ef都能看到:
软中断事件的handler提前注册到softirq子系统,注册方式为open_softirq(softirq_id, handler)
例如,注册网卡收发包(RX/TX)软中断处理函数:
软中断占用了CPU的总开销:可以使用top查看,第三行倒数第二个指标是系统的软中断开销(si字段):
Linux内核源码分析学习地址:ke.qq.com/course/...
文章福利小编推荐自己的Linux内核源码分析交流群:点击加入整理了一些个人觉得比较好的学习书籍、视频资料共享在群文件里面,有需要的可以自行添加哦!
主处理
smpboot.c类似于事件驱动的循环,会调度ksoftirqd线程执行pending的软中断。ksoftirqd内部会进一步调用到__do_softirq,
避免软中断占用过多CPU
软中断的潜在影响:推迟执行的部分(如softirq)可能会占用较长时间,在这段时间内,用户空间线程只能等待。反映在top中,si占比。
不过softirq调度循环对此有所改进,通过budget机制来避免softirq占用过多CPU时间。
硬中断-软中断调用栈
softirq是一种推迟中断处理机制,将IRQ的大部分处理逻辑推迟在这里执行。有两条路径都会执行到softirq主处理逻辑__do_softirq():
1、CPU调度到ksoftirqd线程时,会执行到__do_softirq();
2、每次IRQ handler退出时:do_IRQ()->...
do_IRQ是内核中主要的IRQ处理方式。它执行结束时,会调用exiting_irq(),这会展开成irq_exit()。后者会检查是否pending有softirq,如果有,则唤醒:
进而会使CPU执行到__do_softirq。
软中断触发执行的步骤
总结,每个软中断会经过以下阶段:
以收包软中断为例,IRQ handler并不执行NAPI,只是触发它,在内部会执行到raiseNET_RX_SOFTIRQ;真正的执行在softirq,会调用网卡的poll()方法收包。IRQ handler中会调用napi_schedule(),然后启动NAPI poll()。
需要注意的是,虽然IRQ handler所做的工作很少,但处理这个包的softirq和IRQ在同一CPU上运行。这意味着,如果大量的包都放在同一个RX队列,虽然IRQ开销可能不多,但该CPU仍然会非常繁忙,都花费在softirq上。解决方式:RPS。它不会降低延迟,只是将包重新分配:RXQ->CPU。
三种推迟执行方式(softirq/tasklet/workqueue)
提到,Linux中的三种推迟中断执行方式:
其中:
前面已经看到,Linux在每个CPU上创建了一个ksoftirqd内核线程。
softirqs是在Linux内核编译时确定的,例如网络收包对应的NET_RX_SOFTIRQ软中断。因此是一种静态机制。如果想添加一种新softirq类型,需要修改并重新编译内核。
内部组织
内部由一个数组(或称为向量)管理,每个软中断号对应一个softirq handler。数组与注册:
在5.中所有类型的softirq:
也就是在cat /proc/softirqs看到的哪些。
触发(唤醒)softirq
以收包软中断为例,IRQ handler并不执行NAPI,只是触发它,在内部会执行到raiseNET_RX_SOFTIRQ;真正的执行在softirq,会调用网卡的poll()方法收包。IRQ handler中会调用napi_schedule(),然后启动NAPI poll()。
如果对内核源码有一定了解,会发现softirq使用非常有限,原因之一是它是静态编译的,依赖内置的ksoftirqd线程来调度内置的9种softirq。如果想添加一种新功能,就得修改并重新编译内核,开发成本很高。
实际上,实现推迟执行的更常用方式是tasklet。它构建在softirq机制之上,具体来说就是使用了两种softirq:
换句话说,tasklet是在运行时(runtime)创建和初始化的softirq,
内核软中断子系统初始化了两个per-cpu变量:
tasklet再执行针对list的循环:
tasklet在内核中的使用非常广泛。不过,后面又出现了第三种方式:workqueue。
这也是一种推迟执行机制,与tasklet有些相似,但有显著不同。
使用场景
简而言之,workqueue子系统提供了一个接口,通过该接口可以创建内核线程来处理从其他地方enqueue过来的任务。这些内核线程称为worker threads,内置的per-cpu worker threads:
结构体
kworker线程调度workqueues,原理与ksoftirqd线程调度softirqs类似。然而,我们可以为workqueue创建新的线程,而softirq则不行。
参考资料引用链接
[1]
中断与中断处理:0xax.gitbooks.io/linux-...
作者:赵亚楠 原文:arthurchiao.art/blog/li...来源:云原生实验室