本文是操作系统系列第五篇,介绍操作系统中的中断机制。 中断 异常 系统调用 源头 外设 应用程序 应用程序 响应方式 异步 同步 异步或同步 处理机制 持续,对用户应用程序是透明的 杀死或者重新执行意想不到的应用程序指令 等待和持续 中断描述符表 也称中断描述符表 在操作系统中,会预先设置一些中断处理函数,当CPU接收到中断时,会根据中断号去查找对应的处理函数,中断向量表就是记录中断号和处理函数映射关系的表。 中断处理机制如下: ? ,处理异常 总结 中断机制是为了弥补CPU速度和外设速度数量级差异的机制,它的核心是中断向量表。 本文只介绍概念和简单的机制,没有深入介绍中断过程中特权级转换等内容,有兴趣的同学可以查看清华大学的操作系统课程[1]。
中断的历史原因 在聊中断机制之前,我想先和大家聊一聊中断机制出现的前因后果。 我没有查到中断到底是何时引入的,但是从 Linux 问世以来就已经有了,而且 Linux 是基于 UNIX 开发的,可以认为 UNIX 就已经引入中断机制了,而且换个角度来说,UNIX 作为如此著名的操作系统 ,应该会引入中断机制的。 还有一种处理方式是轮询,现代计算机一般都包含输入输出设备,在轮询机制中,CPU 会不断的顺序询问每个设备是否需要提供服务,如果需要提供服务,CPU 就会转而为设备驱动进行服务;可以看到,这种轮询的方式性能较差 指令就会产生软中断,设备产生的硬中断不会等待太长时间,响应速度比较快,而指令产生的软中断是一种推后的机制,响应速度不如硬中断快。
但是当我们考虑中断事件时,需要明确应该有类似功能的“对象”承担这这样的逻辑。 下面我们主要围绕操作系统的中断机制,Java的中断机制,如何设计一个异步线程间的中断系统这三部分简单探讨下。 Java的中断机制 ---- 理解了上面操作系统的中断之后,Java的中断机制就很easy了 :D Java中断指的是A线程发送中断信号给B线程,B线程再根据自己当前执行程序中的中断处理逻辑决定如何响应 Java的线程中断机制设计的比较灵活,使用者可以决定中断处理的较多事情。 总结下Java中和中断有关的方法: ? 另: 唤醒一个线程只有Java的中断机制可以做,但是如果当前worker不是你能管理的线程池,那么它的中断处理逻辑就控制不了。 那么可以结合与task强绑定的中断标示位和Java中断机制来做,这里前者的作用更多是充当获取到任务的中断结果的作用。
通过中断机制,在外设不需要CPU介入时, CPU可以执行其它任务,而当外设需要CPU时通过产生中断信号使CPU立即中断当前任务来响应中断请求。 Huawei LiteOS的中断支持: 中断初始化。 中断创建。 开/关中断。 恢复中断。 中断使能。 中断屏蔽。 Huawei LiteOS的中断机制支持中断共享。 中断向量表:存储中断向量的存储区,中断向量与中断号对应,中断向量在中断向量表中按照中断号顺序存储。 1.3 运作机制 Huawei LiteOS的中断机制支持中断共享: 中断共享的实现依赖于链表,对应每一个中断号创建一个链表,链表节点中包含注册的中断处理函数和函数入参。 Huawei LiteOS的中断机制支持中断底半部: 中断底半部的实现基于workqueue,在中断处理程序中将工作分为顶半部和底半部,底半部处理程序与work关联,并挂载到合法workqueue上。
Java没有提供一种安全直接的方法来停止某个线程,但是Java提供了中断机制。 如果对Java中断没有一个全面的了解,可能会误以为被中断的线程将立马退出运行,但事实并非如此。 中断机制是如何工作的?捕获或检测到中断后,是抛出InterruptedException还是重设中断状态以及在方法中吞掉中断状态会有什么后果?Thread.stop与中断相比又有哪些异同? 什么情况下需要使用中断?本文将从以上几个方面进行描述。 2. 中断的原理 Java中断机制是一种协作机制,也就是说通过中断并不能直接终止另一个线程,而需要被中断的线程自己处理中断。 中断的处理 既然Java中断机制只是设置被中断线程的中断状态,那么被中断线程该做些什么? 处理时机 显然,作为一种协作机制,不会强求被中断线程一定要在某个点进行处理。 而在某些方面Thread.stop与中断机制有着相似之处。
要处理中断,需要有一个中断处理函数。 这里的返回值有三种:IRQ_NONE 表示不是我的中断,不归我管;IRQ_HANDLED 表示处理完了的中断;IRQ_WAKE_THREAD 表示有一个进程正在等待这个中断,中断处理完了,应该唤醒它。 如果配置了 CONFIG_SPARSE_IRQ,那中断号是不连续的,就不适合用数组保存了。真正中断的发生还是要从硬件开始。这里面有四个层次。第一个层次是外部设备给中断控制器发送物理中断信号。 第二个层次是中断控制器将物理中断信号转换成为中断向量 interrupt vector,发给各个 CPU。 第四个层次是在 IRQ 处理函数中,将 interrupt vector 转化为抽象中断层的中断信号 irq,调用中断信号 irq 对应的中断描述结构里面的 irq_handler_t。
中断又分为外部可屏蔽中断(INTR)和外部非屏蔽中断(NMI),所有I/O 设备产生的中断请求(IRQ)均引起屏蔽中断,而紧急的事件(如硬件故障)引起的故障产生非屏蔽中断。 2、外设可屏蔽中断、异常及非屏蔽中断 Intel x86 通过两片中断控制器8259A 来响应15 个外中断源,每个8259A 可管理8 个中断源。 我们把与中断控制器相连的每条线叫做中断线,要使用中断线,就得进行中断线的申请,就是IRQ(Interrupt ReQuirement ),我们也常把申请一条中断线称为申请一个IRQ 或者是申请一个中断号 TSS 是Intel 所提供的任务切换机制,但是 Linux 并没有采用任务门来进行任务切换。 当控制权通过中断门进入中断处理程序时,处理器清IF 标志,即关中断,以避免嵌套中断的发生。
软中断分析最近工作繁忙,没有时间总结内核相关的一些东西。上次更新博客到了linux内核中断子系统。这次总结一下软中断,也就是softirq。之后还会总结一些tasklet、工作队列机制。 1.为什么要软中断 编写驱动的时候,一个中断产生之后,内核在中断处理函数中可能需要完成很多工作。但是中断处理函数的处理是关闭了中断的。也就是说在响应中断时,系统不能再次响应外部的其它中断。 另外一部分在软件中断中执行,这个时候开启中断,系统可以响应外部中断。 关于软件中断的理论各种书籍都有介绍,不多叙述。而要真正体会软件中断的作用就必须从代码的角度来分析。 只有在进入了软中断处理过程中之后才会开启硬件中断,如果在软件中断处理过程中有硬件中断嵌套,也不会再次调用软中断,because硬件中断是软件中断处理过程中再次进入的,此时preempt_count已经记录了软件中断 对于其它架构的CPU,有可能在触发调用软件中断前,也就是还在处理硬件中断的时候,就已经开启了硬件中断,可能会发生中断嵌套,在中断嵌套中是不允许调用软件中断处理的。Why?
中断上、下半部产生背景 由于内核中中断不允许嵌套,在程序进入中断后,系统会关闭中断接收,这段时间内,其他中断都无法处理导致中断无法响应,因此需要当前进入的中断子服务函数越快越好。 运行机制 (1) tasklet方式: 当下半部处理的事情耗时但是可以忍受时,可以使用tasklet。 tasklet是以软中断形式实现的,软中断的优先级仅次于硬件中断,在进入软件中断时,硬件中断会被打开,因此软件中断可被硬件中断打断。 使用: 软中断实现服务子函数,优先级高,影响系统执行效率。 a. (3) 线程中断:由于工作队列每次只能处理一个中断下半部,但是内核支持多线程,因此出现为每一个中断下半部开辟一个线程处理。将多个中断的下半部线程分配给多个CPU上执行,提高效率。 在程序中调用request_threaded_irq 原型: /* irq: 中断号 * handler: 中断服务子函数 * thread_fn: 中断线程化 * irqflags: 中断触发标志位
看到这我不禁会问自己: 什么是中断机制? 在程序中怎样演绎这个心情就看具体的业务逻辑了,Java 的中断机制就是这么简单 如果还没改变这个先入为主的概念,我怀你没有女朋友()我们拥抱一下 为什么会有中断机制? ,也提供了更多的灵活性,所以当遇到如上场景等,我们就可以考虑使用中断机制了 使用中断机制有哪些注意事项 其实使用中断机制无非就是注意上面说的两项内容: 中断标识 InterruptedException 中断机制贯穿整个并发编程中,这里只简单列觉大家经常会使用的,我们可以通过阅读JDK源码来进一步了解中断机制以及学习如何使用中断机制 ThreadPoolExecutor ThreadPoolExecutor 并发编程中断机制的含义了,它是一种协同机制,和你先入为主的概念完全不一样。
一.中断概述 这篇文章主要记录使用 interrupt() 方法中断线程,以及如何对InterruptedException进行处理。 其实作用不是中断线程,而是「通知线程应该中断了」,具体到底中断还是继续运行,应该由被通知的线程自己处理。 interrupt() 并不能真正的中断线程,这点要谨记。 二.中断相关三个的方法 Thread.interrupt(): 设置中断状态为true Thread.isInterrupted():获取中断状态 Thread.interrupted():获取中断状态 通过Thread.interrupted()能告诉你线程是否发生中断,并将清除中断状态标记,所以程序不会两次通知你线程发生了中断。 即使发生超时,在超时期满之前持续等待也是不可行和不适当的,所以,要使用某种机制使得线程更早地退出被阻塞的状态。
IO机制的重要的方法,比如begin(),end()。 interruptor; //持有实现中断机制的线程对象 private volatile Thread interrupted; protected final void begin nio的channel中断操作,是通过挂载 Interruptible自定义的中断处理对象,当当前线程被中断时,通过回调关闭channel的函数:implCloseChannel,从而实现对当前线程中断的响应 当前线程如何绑定中断机制对象? ,表示Channel因为线程中断而被关闭了,IO操作也随之中断了。
来源: CSDN | phenix_lord的专栏 硬件处理 最近解决一个关于Linux中断的问题,把相关机制整理了一遍,记录在此。 不同的外部设备、不同的体系结构、不同的OS其中断实现机制都有差别,本文对应的OS为linux3.4版本,外部设备为PCI设备、系统为X86。 使用这种机制,中断的数量不受PIR/ IOAPIC等各种器件管脚数量的限制,MSI可以支持32个中断,而MSI-X可以达到2048个;中断的传递相当直接,省略了中断路由的过程;并且能直接从interrupt 这种机制为I/O APIC机制和中PIR机制提供统一的管理界面,该机制使用struct acpi_prt_entry描述INT#和GSI(能和vector、irq对应)的关系,系统中所有的struct ,其它两种机制的初始化(包括相关中断路由信息的初始化)的在《interrupt in linux》中有很详细的描述。
这篇文章以按键为例子讲解linux的中断原理,中断的架构,中断的实现。 在我们的开发中,检测按键是否触发,无非就两种方法—轮询和中断。作者认为两种方法最大的区别就是CPU的利用率。 中断服务程序:相应特定中断时,内核会执行的函数。其中:1、中断处理程序是被内核调用来响应中断的。2、而它们运行于我们称之为中断上下文的特殊上下文中。 中断上下部:为了是程序运行得快和完成的工作量多,将中断处理分为两部分,上半部和下半部,其中,上半部(中断处理程序):接收到中断,立马要执行的程序,只做有严格时限的工作。下半部:允许稍后完成的工作。 handler:指向该中断的中断处理程序 flags:中断标志 name:设备名 dev,用于共享中断线 2、释放中断函数:void free_irq(unsigned int irq,void &pins_desc[0]:用于共享中断线,请求中断和卸载中断会用到。
实现线程的安全中断并不是一件容易的事情,因为Java并不支持安全快速中断线程的机制,这里估计很多同学就会说了,java不是提供了Thread.interrupt 方法中断线程吗,好吧,我们今天就从这个方法开始说起 我没有种中断 我没有种中断 我没有种中断 我没有种中断 我没有种中断is interrupt....... 我没有种中断 我没有种中断 我没有种中断 我没有种中断 我没有种中断 .... 通过结果可以发现子线程并没有中断 所以 Thread.interrupt() 方法并不能中断线程,该方法仅仅告诉线程外部已经有中断请求,至于是否中断还取决于线程自己。 线程的中断状态 由该方法清除。换句话说,如果连续两次调用该方法,则第二次调用将返回 false(在第一次调用已清除了其中断状态之后,且第二次调用检验完中断状态前,当前线程再次中断的情况除外)。 处理不支持中断的线程中断的常用方法 改写线程的interrupt方法 ? ?
while(true) { ... }; 而中断机制会强制中断当前 CPU 所执行的代码,转而去执行先前注册好的中断服务程序。 比较常见的如:时钟中断,它每隔一定时间将中断当前正在执行的任务,并立刻执行预先设置的中断服务程序,从而实现不同任务之间的交替执行,这也是在多任务系统的重要的基础机制。 中断机制主要通过硬件触发,CPU 属于被动接受。有了中断后,各任务执行时间就可以得到非常好的控制。 ? 浏览器提供的 RIC 机制,类似“中断服务”注册机制,注册后我们只要合适的时机进行释放,就能实现“中断”效果,刚也提到对于不同任务之间切换,在中断后,需要考虑现场保护和现场还原。 使用该机制后,对于渲染任务的优先级、撤销、挂起、恢复都能得到非常好的控制。 ? 04 总结 中断机制其实是一种非常重要的解决资源共享的手段,对于操作系统而言,它已经是一个必不可少功能。
因此,Java提供了一种用于停止线程的协商机制―—中断,也即中断标识协商机制。 } new Thread(() -> { isStop = true; }, "t2").start(); } } 中断只是一种协作协商机制 ,Java没有给中断增加任何语法,中断的过程完全需要程序员自己实现。 线程的 中断状态 不受此方法的影响。 由于线程在中断时未处于活动状态而被忽略的线程中断将由此方法反映,返回 false。 中断只是一种协商机制,修改中断标识位仅此而已,不是立刻stop打断 sleep方法抛出InterruptedException后,中断标识也被清空置为false,我们在catch没有通过调用th.interrupt
Java没有提供一种安全直接的方法来停止某个线程,但是Java提供了中断机制。 如果对Java中断没有一个全面的了解,可能会误以为被中断的线程将立马退出运行,但事实并非如此。中断机制是如何工作的? 2.中断的原理 Java中断机制是一种协作机制,也就是说通过中断并不能直接终止另一个线程,而需要被中断的线程自己处理中断。 3.中断的处理 既然Java中断机制只是设置被中断线程的中断状态,那么被中断线程该做些什么? 处理时机 显然,作为一种协作机制,不会强求被中断线程一定要在某个点进行处理。 有些程序可能一检测到中断就立马将线程终止,有些可能是退出当前执行的任务,继续执行下一个任务……作为一种协作机制,这要与中断方协商好,当调用interrupt会发生些什么都是事先知道的,如做一些事务回滚操作 而在某些方面Thread.stop与中断机制有着相似之处。
Java没有提供一种安全直接的方法来停止某个线程,但是Java提供了中断机制。 如果对Java中断没有一个全面的了解,可能会误以为被中断的线程将立马退出运行,但事实并非如此。中断机制是如何工作的? 2.中断的原理 Java中断机制是一种协作机制,也就是说通过中断并不能直接终止另一个线程,而需要被中断的线程自己处理中断。 3.中断的处理 既然Java中断机制只是设置被中断线程的中断状态,那么被中断线程该做些什么? 处理时机 显然,作为一种协作机制,不会强求被中断线程一定要在某个点进行处理。 有些程序可能一检测到中断就立马将线程终止,有些可能是退出当前执行的任务,继续执行下一个任务……作为一种协作机制,这要与中断方协商好,当调用interrupt会发生些什么都是事先知道的,如做一些事务回滚操作 而在某些方面Thread.stop与中断机制有着相似之处。
传统的Thread.interrupt()对原生阻塞调用无效,而NIO通过begin()/end()配对与Interruptible回调机制,在JVM层面架起了一座桥梁,使得Java线程的中断语义能够穿透 这违反了Java的线程中断契约。3.2解决方案:Interruptible回调机制NIO的解决方案是在进入阻塞操作前,向当前线程注册一个“中断回调”。 当虚拟线程被取消或调度器需要unmount它时,carrierthread的中断机制会通过同一个interruptor唤醒底层I/O,确保虚拟线程不会pin住carrierthread。 Go的netpoller使用runtime.notetsleepg和信号量实现阻塞等待,中断通过goroutine调度器的preempt机制实现,不涉及用户可见的中断回调。 8.3vsC++libevent/libuv的事件循环C++库通常不提供内置的线程中断机制,用户需自行通过pipe/eventfd实现唤醒。