免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1343 | 回复: 0
打印 上一主题 下一主题

[内核入门] bottom half [复制链接]

论坛徽章:
13
15-16赛季CBA联赛之八一
日期:2016-07-08 21:00:1415-16赛季CBA联赛之同曦
日期:2017-02-15 14:26:1515-16赛季CBA联赛之佛山
日期:2017-02-20 14:19:2615-16赛季CBA联赛之青岛
日期:2017-05-07 16:49:1115-16赛季CBA联赛之广夏
日期:2017-07-30 09:13:1215-16赛季CBA联赛之广东
日期:2018-07-05 22:34:3615-16赛季CBA联赛之江苏
日期:2018-09-03 12:10:2115-16赛季CBA联赛之上海
日期:2018-09-25 03:49:2215-16赛季CBA联赛之广东
日期:2018-09-25 04:09:12
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2016-11-02 16:24 |只看该作者 |倒序浏览
本帖最后由 _nosay 于 2016-11-02 17:17 编辑

http://bbs.chinaunix.net/thread-4255596-1-1.html(续)

  • bottom half 粗略理解
   
    简单的说,就是将一件完整的事细化,想象一下,如果有个人在食堂窗口打完饭之后,非要吃完再走,导致后面的人都得排队等着,是不是很憋屈?所以食堂里划分了打饭区和用餐区。
    对于计算机来说,如果设计不合理就会导致更严重的后果,比如网络中一个报文经历了重重“磨难”,从发送端到达接收端,却因为接收端关中断而必须重传,大大增加了网络负担。

  • 关中断=可以保护,开不断≠不需要保护
    将比较耗时的处理部分放在开中断时执行,纯粹是为了执行它的时候,CPU仍然能够响应中断,并不代表这段过程允许受到干扰,比如Linux内核为了减轻驱动程序员编写中断处理函数的负担,对于bottom half设计的就很保守,用两"把"锁保护bh函数的执行不被干扰:
    ① bh函数执行途中,当前CPU又产生一次同样的中断,最终又进入该函数执行,所以每个CPU内部有一把锁;
    ② bh函数执行途中,其它CPU又产生一次同样的中断,最终又进入该函数执行,所以所有CPU公共有一把锁。
    除了用锁,还可以像do_IRQ()函数那样用IRQ_INPROGRESS、IRQ_PENDING标记,对某个执行过程进行保护,所以千万不要在“中断的开关”与“保护”之间完全画等号。
  (内核很多对于同一个问题的不同解决方案,有时候没有明显的好坏之分,好的内核或驱动程序员,应该根据自己的应用场景,尽量选择合适的机制,让整个系统能更好的运行)

  • 软中断由来
    上述提到bottom half缓解了中断丢失的问题,但对bh函数的保护做的过于保守,而软中断是基于对保守程度的放开,设计的一种新框架,并且为了兼容老的bh函数(依赖于老框架的充分保护),即保留bottom half机制,也就是在softirq机制的基础上再多加一些保护罢了。
  (学内核时深刻体会到一种感觉:永无止境。经常当感觉这样已经很好了的时候,新版本的内核又设计出更精妙或更完善的方案,所以说学习内核可以治心浮气躁,让心静下来

  • softirq过程
    ① 初始化
        softirq_init()函数用于整个软中断框架的初始化(只初始化了两种软中断:HI_SOFTIRQ、TASKLET_SOFTIRQ,其它用于以后扩展,以及基于HI_SOFTIRQ软中断的bottom half框架初始化);
        将来某些内核子模块需要使用某种软中断时,该子模块初始化时需要调用相应接口,注册软中断函数,比如init_bh()。
   

    ② 软中断的产生及响应
        软中断与硬中断最根本的区别,就是执行真正中断服务函数的时机不同,“软中断服务函数”并不是在硬件产生中断时CPU自动跳转到的那段代码内直接执行,为了事后知道刚才产生了哪种中断,需要“标记”下来(对于软中断来说,就是“产生”)。
      (这应该就是“软中断”这个名字的由来,一方面硬中断的产生是通过硬件上的INTR引线获知,而软中断是通过软件中的变量获知,另一方面相对于硬中断处理函数,它的时间要求更“缓和”、硬件要求也更“缓和”(不要求关中断))
        如同文件系统中,每个文件对应的dentry只有一个,但多个进程或同一进程,可以有多个file结构表示对该文件的操作上下文。软中断框架中softirq_vec[32]、bh_task_vec[32]、bh_base[32]等在整个内存中只有一份,但每个CPU的“软中断状态信息”,各自独自占有一份(所以softirq相对于bottom half,就解放了所有CPU之间的那把锁,而加上更严格的限制,就可以兼容bottom half):
     
        关键是__softirq_active、__local_irq_mask,它们都占32位,当它们第x位都为1时,执行softirq_vec[x].action()函数,通过上面的open_softirq()函数可以看出,在打开HI_SOFTIRQ、TASKLET_SOFTIRQ“软中断通道”的同时,也将各个CPU的mask相应位也打开了。
        而tasklet_hi_vec[NR_CPUS]是各个CPU希望通过软中断框架最终执行的函数,即刚刚“标记”并挂到链表的函数,比如将__localirq_active的第0位打开,是希望通过softirq_vec[x].action()指向的tasklet_hi_action()函数,从softirq框架“过渡”到bottom half框架,那里就会用到该CPU对应的tasklet_hi_vec[].list,依次执行“产生”中断时,挂在上面的hb函数:
   

     另外,什么时候“产生”中断?什么时候响应中断?
     硬件产生时钟中断时,执行do_timer(),里面只是“产生”一下软中断,很快就返回了:
   

   

     每次硬中断执行完处理函数,或从系统调用返回时,会判断是否需要执行软中断处理函数:
   

   

    ③ HI_SOFTIRQ、TASKLET_SOFTIRQ软中断比
        HI_SOFTIRQ软中断最终要执行的,通过bh_task_vec[x]挂到链表里的bh函数链,由tasklet_hi_action()→bh_action()函数“包装”,外面加了锁;
        TASKLET_SOFTIRQ软中断最终要执行的,也是通过bh_task_vec[x]挂到链表里,由tasklet_action()函数“包装”,外面没有加锁。
        所以,如果某个软中断服务函数,可以多CPU并行执行,但必须要求硬件关中断,就可以注册为TASKLET_SOFTIRQ。

  • 三个很相似的概念
    ① 硬中断:外部设备对CPU的中断
    ② 软中断:“硬中断服务程序”对内核的中断
    ③ 信号:内核(或其它进程)对某个进程的中断(详见《Linux内核源代码情景分析》6.8节)
  (概念不是用来咬文嚼字的,是用来更简单的表达和更方便理解,所以思想的传播需要概念,你如果正在抱怨概念,那肯定是在抱怨自己不肯努力去理解它们

评分

参与人数 1可用积分 +10 收起 理由
amarant + 10 感谢分享

查看全部评分

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP