Linux中断子系统问题汇总

1.发生硬件中断后,ARM处理器做了那些事情?

(1)CPU自动保存处理器状态,即将中断发生时的CPSR寄存器内容保存到SPSR_irq寄存器中
(2)CPU自动设置当前程序状态寄存器CPSR的低5位,使处理器进入特权模式中的IRQ模式(Linux不使用FIQ,只使用IRQ)
(3)硬件自动关闭IRQ中断
(4)将返回地址(PC)自动保存到LR_irq寄存器中
(5)CPU自动的将程序计数器PC设置成异常中断向量表中的地址,进入相应的异常处理程序中处理中断
(6)处理完中断后,恢复中断发生前的处理器状态,即将SPSR_irq寄存器中的数据复制到CPSR寄存器中
(7)设置程序计数器PC,使其指向中断发生前要执行的指令,即将LR_irq寄存器中的数据复制到PC寄存器中

2.Linux内核中硬件中断号如何映射为软件(虚拟)中断号?

映射过程如下图所示,可总结如下。
(1)驱动中调用platform_get_irq,进行中断映射
(2)将设备树中的中断引脚号转换为硬件中断号
(3)从位图allocated_irqs中获取为0的bit编号,此编号就是软件(虚拟)中断号
(4)初始化irq_desc(每一个中断都对应一个irq_desc结构体)。若是线性映射,则是直接初始化静态定义的struct irq_desc结构体数组,数组索引为软件中断号。若是非线性映射,则动态分配struct irq_desc结构体,将虚拟中断号设置到irq_data中,然后将软件中断号和对应的irq_desc结构指针插入到基数树irq_desc_tree中,key为软件中断号。定义CONFIG_SPARSE_IRQ宏时为非线性映射,反之为线性映射。
(5)将硬件中断号设置到irq_data中。
(6)设置中断处理函数,该中断处理函数会遍历struct irq_desc结构体中的action链表,调用所有的中断处理函数。
(7)保存映射规则。若是线性映射,则将软件中断号保存到linear_revmap数组中,该数组的索引为硬件中断号。若是非线性映射,则将硬件中断号和对应struct irq_desc结构体的irq_data指针插入到基数树revmap_tree中,key为硬件中断号。
(8)设置中断触发方式。
中断号映射过程

3.硬件中断发生后,Linux内核如何响应并处理呢?怎么利用硬件中断号找到软件(虚拟)中断号?怎么利用软件(虚拟)中断号找到irq_desc数据结构?

中断处理流程

4.irq_desc的组织形式?

irq_desc的组织形式

5.Linux中断子系统关键数据结构之间的关系?

Linux中断子系统关键数据结构关系图

6.在SMP系统中,中断发给那个CPU由什么决定?

由GIC中断控制器的GICD_ITARGETSRs寄存器设置,每8bit设置一个中断的目标CPU,,bit0代表CPU0,bit1代表CPU1,依次类推。当对应的bit为0时,表示不可发送给对应的CPU,当对应的bit为1时,表示可发送给对应的CPU。

7.为什么说中断上下文不能执行睡眠操作?

中断执行的过程可总结如下:
发生中断->CPU关中断->执行中断上半部分->CPU开中断->执行softirq或tasklet->CPU关中断->中断退出同时打开CPU中断->中断处理线程、软中断处理线程、工作队列
(1)中断上半部分是在CPU关中断的情况下执行,若睡眠。则永远无法被唤醒,CPU再也不响应中断,导致系统不能正常工作,因此中断上半部分不能睡眠。
(2)softirq或tasklet是在CPU开中断的情况下执行,这里要区分能不能睡眠和可不可以睡眠两种情况。睡眠本质上是让出CPU,保存当前的上下文,然后恢复下一个进程的上下文,若中断的上下文能正确保存,同时在合适的时机能恢复并且得到正确执行,则从技术上来说,是可以睡眠的。ARM平台的测试程序如下,在以太网的NAPI接收软中断处理函数中调用schedule进行上下文切换,同时打印出schedule前后的pid及当前进程的th​​read_info地址。

测试程序
测试结果如下图所示,软中断调用schedule后能被正确的调度回来,且得到了正确执行,schedule前后的pid和th​​read_info地址一致。但是两次schedule的pid和th​​read_info地址不一致,说明ARM的中断上下文保存到了被打断进程的内核栈中,调度器可通过task_struct结构体恢复中断上下文,因此可以被调度回来(x86有独立的中断栈,中断上下文保存在中断栈中,调度器无法通过task_struct结构体恢复中断上下文,调用schedule后再也无法被调度回来,因此不能睡眠),。因此从技术上,软中断是可以睡眠的。但是软中断毕竟处于中断上下文,处于中断上下文其他进程得不到调度,若在软中断中睡眠,则软中断执行时间无法控制,可能会很长,会导致系统的实时性下降,因此,从使用的角度看,软中断不应该睡眠,在软中断中schedule调度,内核也输出了BUG信息,软中断处于原子上下文,不应该schedule调度。
软中断睡眠测试结果
(3)中断处理线程、软中断处理线程、工作队列的执行环境处于进程上下文,因此可以睡眠。

8.request_thread_irq创建的中断处理线程的优先级是多少?

优先级为50,调度策略为SCHED_FIFO

9.软中断的回调函数执行过程中是否允许响应本地中断?

允许响应本地中断,软中断是在开中断的情况下执行

10.同一类型的软中断是否允许在多个CPU并行执行呢?

同一种软中断(softirq)的处理函数可以在多个处理器上同时执行,处理函数必须是可以重入的,需要使用锁保护临界区。同一个小任务(tasklet)同一时刻只能在一个处理器上执行,不需要处理函数是可重入的。

11.软中断上下文和进程上下文那个优先级高?为什么?

软中断实际上处于中断上下文,只是打开了本地CPU中断,中断的优先级高于进程的优先级。

12.是否运行同一个tasklet在多个CPU上并行执行?

同一个小任务(tasklet)同一时刻只能在一个处理器上执行,不允许在多个CPU上并行执行。

13.workqueue运行在中断上下文还是进程上下文?其回调函数允许睡眠吗?

workqueue运行在进程上下文,回调函数允许睡眠。

15.CMWQ机制如何动态管理工作线程池的线程呢?

(1)工作线程有3中状态:空闲(idle)、运行(running)和挂起(suspend)。空闲是指没有执行工作,运行是指正在执行工作,挂起是指执行工作的过程中睡眠。
(2)如果工作线程池中有工作任务要处理,则至少要有一个处于运行状态的线程来处理。
(3)如果处于运行状态的工人在执行工作的过程中进入了挂起状态,为了保证其他工作的执行,需要唤醒空闲的线程处理。
(4)如果有工作任务需要执行,并且处在运行状态的工作线程的数量大于1,会让多余的工作线程进入空闲状态(进程进行上下文切换时,在__schedule函数中会判断此进程是否是工作队列的工作线程,如是则会调用wq_worker_sleeping函数判断是否需要唤醒其他工作线程,如需要则调用try_to_wake_up_local尝试唤醒)。
(5)如果没有工作任务需要执行,则让所有的工作线程进入空闲状态。
(6)如果工作线程的空闲时间超过300秒,则自会被销毁。

16.如果有多个work挂入一个工作线程中执行,当某个work的回调函数阻塞了,那剩下的work该怎么办?

回调函数阻塞时会调用schedule让出CPU,schedule函数会检查工作队列状态,若没有线程处于运行状态且有work要处理,则会唤醒一个空闲线程来继续处理其他的work。

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值