kernel笔记——中断
cpu与磁盘、网卡、键盘等外围设备(相对于cpu和内存而言)交互时,cpu下发I/O请求到这些设备后,相对cpu的处理能力而言,磁盘、网卡等设备需要较长时间完成请求处理。
那么在请求发出到处理完成这段时间,应如何设定cpu的行为,既能让这期间运行的其他程序得到执行,又能在外设处理完成后,cpu及时获取到处理完成的消息?
可以按以下方式设定cpu行为:
- cpu以轮询(polling)的方式,每隔一段时间询问请求是否处理完成
- cpu下发请求后执行其他进程,磁盘等外设完成处理后,主动告知cpu
对于第1种方式,轮询会带来不必要的cpu消耗。第2种是现行的方式,外设通过电信号告知cpu的机制被称为中断(interrupt)。
IRQ line与ISR
不同设备发起的中断以不同的数值标识,这些标识中断的数值被称为中断请求线(interrupt request line, IRQ line),IRQ line与中断的关系相当于系统调用号与系统调用的关系。
cpu接收到中断后会将中断递交给内核处理,内核中有相应的函数完成中断处理(interrupt handler或interrupt service routine,ISR)。
中断上下文
每个中断对应一个中断处理函数,当中断处理函数被调用时,内核处于中断上下文(interrupt context)。不同于进程上下文(process context),中断处理过程中不能发生阻塞、休眠,即不进行进程调度,其基于以下原因:
- 中断处理函数需要较快的响应速度,尽快告知外设已接收到中断的消息,以让外设继续工作
- 中断处理中没有独立的函数栈,如果被调度,不会保存寄存器的值,因而回不到调度前执行的代码
中断屏蔽
从是否可屏蔽的角度,中断可分为:
- 可屏蔽中断(maskable interrupt): 可通过设定中断屏蔽寄存器EFLAGS中IF标志位关闭的中断
- 不可屏蔽中断(non-maskable interrupt, NMI): 无法通过设置标志位屏蔽的中断,如电源掉电、时钟中断
对于可屏蔽中断,关闭中断的方式有以下3种:
- 使用cli(clear interrupt)指令,在全局范围关闭所有中断,使用sti(set interrupt)指令恢复
- 调用local_irq_disable或local_irq_save关闭当前cpu中断,使用local_irq_enable或local_irq_restore恢复
- 调用disable_irq或disable_irq_nosync在全局范围关闭某一特定中断线,使用enable_irq或synchronize_irq恢复
因中断是异步的,屏蔽中断可用于防止中断嵌套。非正常的中断关闭会带来很多不良结果,例如cpu不响应键盘中断时,用户无法使用键盘操作;又例如cpu不响应时钟中断,则不能进行进程调度,依赖于时钟中断的任务都无法完成,机器基本变成僵尸。
中断处理流程
外设发起中断,cpu接收中断并传递给内核处理,下图说明了该过程:
内核代码中,中断号被传递到do_IRQ处理,do_IRQ调用__do_IRQ函数,__do_IRQ中调用handle_IRQ_event函数,其调用相应的中断处理函数进行中断处理;处理完成,返回到do_IRQ函数,之后调用irq_exit,在irq_exit函数中,调用do_softirq处理软中断,软中断相关内容将在后文讲述。
proc接口
proc文件系统向用户开放了各个中断的情况:
linux # cat /proc/interruptsCPU0 CPU1 0: 178037 155726 IO-APIC-edge timer 1: 49578 7372 IO-APIC-edge i8042 8: 34 23 IO-APIC-edge rtc0 …… NMI: 0 0 Non-maskable interrupts LOC: 85437 86438 Local timer interrupts ……
以上输出显示了中断号、各个cpu接收中断次数、中断控制器(interrupt controller)和中断名称等信息,从/proc/stat也可查到中断相关信息。
cpu亲和力
多核cpu给中断处理方式带来了新的问题:若某个中断到来,应该由哪个核处理?
我们可以通过proc的接口,设定特定的cpu处理某个中断,这被称为cpu对中断的亲和力(affinity),利用/proc/irq/{interrupt num}/smp_affinity可以查看或设定cpu亲和力:
linux# cat /proc/irq/[0,1]/smp_affinity 3 1
以上查询结果显示,0号、1号cpu均可处理0号中断,而1号中断更倾向于交给1号cpu处理。若要设定1号cpu处理1号中断,可执行以下命令:
linux # echo 2 > /proc/irq/1/smp_affinity
中断负载平衡
irqbalance为用户态下的一个守护进程,其可平均地在多核cpu间分发中断:
linux # ps -elf | grep irqbalance | grep -v grep 1 S root 2408 1 0 80 0 - 2242 - Jul12 ? 00:00:01 /usr/sbin/irqbalance
下半部
内核接收到cpu传递过来的中断后,为做到快速响应外设,中断的处理被分成两部分:
- 上半部(top halves):不得不做的工作放在上半部,也即中断处理程序中,例如告知外设接收到中断、将数据从外设中拷贝到内存
- 下半部(bottom halves):不紧急的工作延后完成,如处理上半部中从外设拷贝来的数据
例如网卡接收数据过程中,首先网卡发起中断告诉cpu取数据,然后内核从网卡读取数据存入缓存,再之后内核解析数据并将数据送到应用层。如果以上工作都让中断处理程序来处理,过程太长,会导致丢失新来的中断。更优的方式是将以上工作分成两部分,从网卡读取数据到缓存由上半部完成,解析数据等较不紧急的工作由下半部完成。
下面我们看softirq和tasklet两种下半部实现方式。
softirq
softirq在2.3版本内核被引入,相关代码在中定义,内核中直接使用softirq的场景较少。
可用的softirq有以下几种,在中定义:
enum { HI_SOFTIRQ=0, TIMER_SOFTIRQ, NET_TX_SOFTIRQ, NET_RX_SOFTIRQ, BLOCK_SOFTIRQ, BLOCK_IOPOLL_SOFTIRQ, TASKLET_SOFTIRQ, SCHED_SOFTIRQ, HRTIMER_SOFTIRQ, RCU_SOFTIRQ, /* Preferable RCU should always be the last softirq */ NR_SOFTIRQS };
提交一个softirq需要调用raise_softirq函数,raise_softirq调用raise_softirq_irqoff,该函数将相应软中断标识为pending、完成软中断提交。
标识为pending的软中断可在以下时机得到处理:
1. 硬中断处理完成、do_IRQ函数即将返回时处理
do_IRQ调用irq_exit函数,irq_exit调用invoke_softirq,即do_softirq函数,do_softirq调用__do_softirq。在__do_softirq函数中,最多处理10个软中断,若软中断的个数超过10,则调用wakeup_softirq唤醒ksoftirqd内核线程进行软中断处理
2. ksoftirqd内核线程被唤醒后处理
以上说明了ksoftirqd线程被唤醒的一种情况,wakeup_softirqd还会在raise_softirq_irqoff函数中被调用,也即软中断被提交之后,可唤醒ksoftirqd完成软中断处理
3. 显式地调用do_softirq进行软中断处理
在内核网络代码中,netif_rx_ni函数会主动调用do_softirq进行软中断处理
tasklet
tasklet基于softirq实现,其本质也是softirq,对应softirq枚举类型中的HI_SOFTIRQ和TASKLET_SOFTIRQ,HI_SOFTIRQ优先级较高。
相比softirq,即使相同类型的softirq也可同时在不同的cpu上处理,而相同类型的tasklet不可同时在不同cpu上处理,不同类型的tasklet可以。
可通过tasklet_schedule或tasklet_hi_schedule提交tasklet,这两个函数最终调用raise_softirq_irqoff提交软中断。
因tasklet提交的同样是软中断,所以还是由do_softirq函数完成tasklet的处理。
Reference: Chapter 7 and chapter 8, Linux kernel development.3rd.Edition
转载于:https://www.cnblogs.com/felixzh/p/9047712.html
kernel笔记——中断相关推荐
- linux kernel的中断子系统之(三):IRQ number和中断描述符【转】
转自:http://www.wowotech.net/linux_kenrel/interrupt_descriptor.html 一.前言 本文主要围绕IRQ number和中断描述符(interr ...
- Linux kernel的中断子系统之(九):tasklet
返回目录:<ARM-Linux中断系统>. 总结: 二介绍了tasklet存在的意义. 三介绍了通过tasklet_struct来抽想一个tasklet,每个CPU维护一个tasklet链 ...
- DSP28335笔记 ———— 中断系统 之 外部中断
DSP28335笔记 ---- 中断系统 之 外部中断 我用的开发板是"硬汉DSP28335开发板",文中对于硬件的描述可以说是没有,而且我还没有附上电路图希望在看的朋友不要喷我. ...
- ZYNQ PS端模块读书笔记-中断
作者:ShownSun 工作室:时沿科技 文章目录 ZYNQ PS端模块读书笔记-中断 0 引言 1 环境 1.1 私有.共享和软件中断 1.2 通用中断控制器 1.3 复位和时钟 1.4 模块框图 ...
- linux kernel的中断子系统之(三):IRQ number和中断描述符
原文地址 http://www.wowotech.net/linux_kenrel/interrupt_descriptor.html linux kernel的中断子系统之(三):IRQ numbe ...
- 51单片机笔记:中断系统
单片机笔记 中断系统 工作原理 功能描述 终止当前进行的事件,去处理突发需及时处理的事件,处理完还要返回原事件. 中断符函数 void ISR() interupt n 中断符函数与普通函数区别 普通 ...
- 009 - STM32学习笔记 - 中断
009 - STM32学习笔记 - 中断 这节的内容,野火的官方视频我反复看了好几次,但是感觉火哥在这块讲解的特别绕,理解起来很吃力,后来在看了一下其他老师的视频,结合一些书本资料和官方手册,才搞清楚 ...
- linux-2.6.18源码分析笔记---中断
一.中断初始化 中断的一些硬件机制不做过多的描述,只介绍一些和linux实现比较贴近的机制,便于理解代码. 1.1 关于intel和linux几种门的简介 intel提供了4种门:系统门,中断门,陷阱 ...
- 字符设备驱动笔记——中断方式按键驱动之linux异常处理结构(四)
1.中断方式获取按键值单片机: 1)按键按下 2)cup发生中断,跳转到异常向量入口执行 3)b 函数a.保存被中断的现场b.执行中断处理函数c.恢复 linux: 1)trap_init()函数构造 ...
最新文章
- MATLAB实战系列(三十六)-MATLAB 离散Hopfield神经网络的分类——高校科研能力评价
- Office SharePoint Server 2007 中的 Workflow
- linux ce mysql安装_Linux 安装 MySQL 8.0
- Python 第十一章 常用第三方模块
- Java 中15种锁的介绍:公平锁,可重入锁,独享锁,互斥锁,乐观锁,分段锁,自旋锁等等
- 写个随笔解解闷-书签漫游
- windows安装zabbix客户端
- Java 开发环境配置jdk安装教程
- Python科学库sklearn.numpy.scipy. matplotlib.pandas
- Android循环ViewPager(二)
- 华为NP课程笔记2-OSPF2
- 最近做一个新闻类项目,用到调用新浪微博接口,经过研究测试整理步骤如下:先根据此内容获取App Key和Secret Key
- 插值算法的Python实现方式
- 2022电大国家开放大学网上形考任务-民事诉讼法学非免费(非答案)
- 什么是APS高级计划排程系统?APS计划排产有什么功能和作用?
- DDR4内存大小等信息计算
- C语言 输入一个正整数,判断它是素数还是合数
- 【转载】城域网IPv6过渡技术—NAT444与DS-lite详解
- 移动硬盘出现乱码文件夹的解决方法
- 易语言 Visual Basic 6.0 (VB6)