中断上下文简要概述

中断上下文主要是硬件中断上下文 软件中断上下文 和 BH临界区上下文

中断上下文你主要分为以下两种情况
(1)执行该中断的处理函数(我们一般称之interrupt handler或者叫做top half),也就是hard interrupt context
(2)执行软中断处理函数,执行tasklet函数,执行timer callback函数。(或者统称bottom half),也就是software interrupt context。
top half当然是绝对的interrupt context,但对于上面的第二种情况,稍微有些复杂,其执行的现场包括:
(1)执行完top half,立刻启动bottom half的执行ss
(2)当负荷比较重的时候(中断产生的比较多),系统在一段时间内都在处理interrupt handler以及相关的softirq,从而导致无法调度到进程执行,这时候,linux kernel采用了将softirq推迟到softirqd这个内核线程中执行
(3)进程在内核态运行的时候,由于内核同步的需求,需要使用local_bh_disable/local_bh_enable来保护临界区。在临界区代码执行的时候,有可能中断触发并raise softirq,但是由于softirq处于disable状态从而在中断返回的时候没有办法invoke softirq的执行,当调用local_bh_enable的时候,会调用已经触发的那个softirq handler。
对于上面的情况1和情况3,毫无疑问,绝对的中断上下文,执行现场的current task和softirq handler没有任何的关系。对于情况2,虽然是在专属的内核线程中执行,但是我也倾向将其归入software interrupt context。

中断是短暂的 linux内核的大部分时间都是各种进程切来切去 一会儿运行在进程的用户空间,一会儿通过系统调用进入内核空间 当时系统不是封闭的 也要和外设等交互 这是就要通过中断上下文 外省硬件的交互 最后把数据交付进程或者进程将数据传递给外设 进程上下文有丰富的、属于自己的资源:例如有硬件上下文,有用户栈、有内核栈,有用户空间的正文段、数据段等等。而中断上下文什么也没有,只有一段执行代码及其附属的数据 所以当中断发生的时候,遇到哪一个进程就借用哪一个进程的资源 这也就导致了中断上下文不能睡眠的原因

LINUX提供了几个函数判断是在哪个context
#define in_irq() (hardirq_count())
#define hardirq_count() (preempt_count() & HARDIRQ_MASK)
top half的处理是被irq_enter()和irq_exit()所包围,在irq_enter函数中会调用preempt_count_add(HARDIRQ_OFFSET),为hardirq count的bit field增加1。在irq_exit函数中,会调用preempt_count_sub(HARDIRQ_OFFSET),为hardirq count的bit field减去1。因此,只要in_irq非零,则说明在中断上下文并且处于top half部分。

解决了hard interrupt context,我们来看software interrupt context。
#define in_serving_softirq() (softirq_count() & SOFTIRQ_OFFSET)

这个函数是直接的判断是否在Software interrupt context
还有一个类似的函数
#define in_softirq() (softirq_count())
#define softirq_count() (preempt_count() & SOFTIRQ_MASK)
这是判断是否在Software interrupt context 和进程上下文中disable bottom half的临界区部分

#define in_interrupt() (irq_count())
#define irq_count() (preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK \
| NMI_MASK))
这是hard interrupt contxt software interrupt context 上禁止softirq情况下的进程上下文

中断上下文不能sleep的原因
当然,linux的设计并非如此(其实在rt linux中已经有了这样的苗头,可以参考中断线程化的文章),中断handler以及bottom half(不包括workqueue)都是在interrupt context中执行。当然一提到context,各种资源还是要存在的,例如说内核栈、例如说memory space等,interrupt context虽然单薄,但是可以借尸还魂。当中断产生的那一个时刻,当前进程有幸成为interrupt context的壳,提供了内核栈,保存了hardware context,此外各种资源(例如mm_struct)也是借用当前进程的。本来呢interrupt context身轻如燕,没有依赖的task,调度器其实是不知道如何调度interrupt context的(它处理的都是task),在interrupt context借了一个外壳后,从理论上将,调度器是完全可以block该interrupt context执行,并将其他的task调入进入running状态。然而,block该interrupt context执行也就block其外壳task的执行,多么的不公平,多么的不确定,中断命中你,你就活该被schedule out,拥有正常思维的linux应该不会这么做的。
因此,在中断上下文中(包括hard interrupt context和software interrupt context)不能睡眠。

文章来自阅读于蜗窝科技 http://www.wowotech.net/

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值