0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

为什么要把软中断锁放到更底层去呢?

Linux阅码场 来源:Linux阅码场 2023-08-24 09:04 次阅读

大内核锁(BKL)现在已经成为了一个遥远的记忆,但在那么多年里,它都是内核开发社区面临的一项棘手问题。然而 BKL 的终结并不意味着内核没有其他有问题的锁。近来,已经有一些关注转向了软中断锁(software-interrupt lock)或“下半部锁”(bottom half lock),因为它可能会在实时系统上导致延迟。Frederic Weisbecker 正在采取最新行动来减小这个锁的影响范围,该方法就是基于移除 BKL 时所采取的方法。

最初,Linux 内核是在单处理器系统上开发的 —— 当然可以理解,因为那时我们手头只有这种系统 —— 因此,代码在很大程度上基于这样的假设:它在 CPU 上运行,完全不存在其他的 CPU。于是 BKL 最终需要被引入,才能让 Linux 能够运行在那些产业分析师向我们保证的未来将会大行其道的多处理器机器上。它确保了只有一个 CPU 在任何给定时间内运行内核代码,从而避免了各种并发问题,但是显著地牺牲了性能,尤其是随着 CPU 数量的增加而更加明显。人们很快意识到 BKL 必须被移除。

在许多子系统中采取的方法是将 BKL 下移至系统的更底层级别。不再是在调用每个驱动程序的 open()函数时就申请持有 BKL,而是修改每个驱动程序来自行获取 BKL。然后,open()函数可以在不持有 BKL 的情况下安全地得到调用了,每个驱动程序可以在需要时进行独立的审查(audit)和修复,之后可以删除其对 BKL 的使用。这种把 BKL 下移的动作将一个大问题分解成了许多较小且更易处理的问题。经过多年的努力,BKL 终于在 2011 年被移除了。

软中断(software interrupt)是一种延后执行的方法,用于执行一些是紧急但又无法直接在硬件中断上下文中执行的工作。当有这种工作要做时,子系统会通过设置一个 flag 来触发软中断;这会使得在下一个合适的时机会调用其处理程序,通常是在硬件中断处理完成后就立即调用,或在从系统调用返回到用户空间之前调用。如果处理时间过长,相关处理也可以推送到专门的 ksoftirqd 线程中。

软中断有许多使用者,包括 tasklets、网络、块设备子系统、读-拷贝-更新(RCU)以及内核定时器。在某些工作场景中,软中断处理可能成为 CPU 总负载的一个重要部分;它可能会运行相当长的时间,从而对运行在用户空间中的软件导致延迟。会禁用软中断处理的那些内核代码(为了避免与处理程序的产生 race condition)会变成不可抢占的,这也会导致出现不太愉快的延迟。总之,与 BKL 一样,软中断反映了几十年前很适用但是现在存在问题的一种设计。

其中一个设计上的决策是,软中断处理程序需要互斥;在任何给定的 CPU 上,只能执行一个软中断处理程序。因此,如果块设备的软中断处理程序运行时间很长,那么网络和定时器处理程序可能就会被无限期地延迟。即使不同类型的软中断处理程序之间很少出现竞争,情况仍然是如此。没有确切的方法可以确定同时运行两个处理程序是否安全,因此人们不会这样做。

Weisbecker 的 patch set 旨在通过在定时器子系统中采用 BKL 方式的迁移到更底层实现的方法来解决这个问题。定时器函数会在内核的各个地方被放到队列里等待调用;它们往往是互相独立的,与其他软中断处理程序并不会产生并发问题。几乎所有的定时器函数都可以与其他软中断处理完全并发地运行 —— 但是这里说的是“几乎”。在没有确定每个定时器函数的安全性的情况下,使定时器处理完全独立于软中断处理可能会引入很难调试的问题。

相反,Weisbecker 采取了分成两步的方法来增加定时器处理的并发性。第一步是允许单个软中断向量在不完全禁用软中断处理的情况下被禁用。这个 patch set 的目的是允许定时器函数与其他软中断并发运行,但它们仍然不会跟彼此并发运行。通过禁用定时器事件的处理(在本地 CPU 上),定时器处理程序可以安全地重新启用软中断处理,而无需担心会再次调用它。

第二步是允许单个 timer 函数来通知到定时器(timer)子系统,说它们可以跟其他软中断处理并发运行。任何不会与软中断处理程序竞争、或者在需要时得执行自己的软中断禁用代码的定时器函数,都可以在设置其定时器事件时添加 TIMER_SOFTINTERRUPTIBLE flag 来标记。当定时器子系统看到此标志时,就会在该定时器函数运行时重新启用软中断处理。因此,如果出现更重要的工作的话,这个 timer 函数就可以被抢占。

在 patch set 中只有一个定时器函数 process_timeout()是以这种方式标记的。然而,Weisbecker 期待着“几年后”的一天内核的所有定时器函数都已经过 audit,并可以安全地与软中断处理程序并发运行;在那时,将可以完全从软中断机制中移除定时器处理。这样以来就是朝着最终消除软中断的一个小步骤。

显然,需要进行相当多的工作才能达到这一点。即使这个 patch set 也需要“更多微调”,以使可以中断的 timer 函数能够抢占其他软中断处理程序,这是解决问题的重要部分。但是,如果这项工作能够进入 mainline 的话,它可能就能代表着朝着这个方向迈出了一步。Weisbecker 现在已经尝试了几次解决软中断的问题,但没有取得太大的成功。然而最终,就像 BKL 一样,正确的方法将会被找到,长期存在的问题终将得到解决。






审核编辑:刘清

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 处理器
    +关注

    关注

    68

    文章

    18275

    浏览量

    222164
  • cpu
    cpu
    +关注

    关注

    68

    文章

    10442

    浏览量

    206564
  • 定时器
    +关注

    关注

    23

    文章

    3147

    浏览量

    112037
  • LINUX内核
    +关注

    关注

    1

    文章

    311

    浏览量

    21389
  • 软中断
    +关注

    关注

    0

    文章

    8

    浏览量

    2983

原文标题:LWN:把软中断锁放到更底层去!

文章出处:【微信号:LinuxDev,微信公众号:Linux阅码场】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    请问TC39x如何将变量放到自定义的段中去呢

    哪位知道如何将变量放到自定义的段中去呢?__attribute__ ((section(\".MySec\")))const tU32 M_A1 = 0
    发表于 01-31 08:18

    ST32F103单片机烧录程序,有段数据需要存放到flash中,怎么操作?

    ST32F103单片机烧录程序,有段数据需要存放到flash中,怎么生成的hex中带这段数据,直接烧录程序就一起把这段数据烧录进去呢
    发表于 04-19 07:28

    STVD中断函数如何调用才能放到主函数使用?

    我用的是STVD,一直研究定时器4中断,网上找了很多资料,现在是定时器4中断可以正常工作,但是中断函数只能写在stm8_interrupt_vector.c这个里面,如果写到主函数就会报错,请各位大神帮忙看下如何调用才能
    发表于 04-26 06:25

    已解决_紧急救助-如何把贴片元件放到底层

    本帖最后由 lsergao 于 2013-3-29 07:53 编辑 我把一个贴片元件双击选择放到底层,怎么打印底层没有焊盘啊,请高手指点,我是一个新手
    发表于 03-28 16:39

    stm32中断仿真

    用Keil进行stm32的中断仿真,进不了中断,请高手解答。多谢!
    发表于 04-06 07:10

    【安富莱】【RTX操作系统教程】第11章 临界段,任务中断

    第11章 临界段,任务中断 本章教程为大家讲解几个重要的概念,临界段,任务中断。 本
    发表于 01-25 16:52

    转第16章 FreeRTOS调度,任务中断

    第16章 FreeRTOS调度,任务中断本章教程为大家讲解调度,任务
    发表于 09-01 07:45

    第11章 临界段,任务中断

    转rtx操作系统 本章教程为大家讲解几个重要的概念,临界段,任务中断。本章教程配套的例子含Cortex-M3内核的STM32F103和Cortex-M4内核的STM32F407。11.1 临界
    发表于 10-04 19:58

    请问硬仿和仿哪个时间准确?

    硬仿和放时间不一样,不知道是为什么,哪个时间准确啊
    发表于 08-07 06:59

    请问一下中断的问题如何解决

    我想让程序运行到某一行时产生一个中断,是不是用中断的方式及调用EXTI_GenerateSWInterrupt()这个函数,还有什么其他的方法没有。如果只用
    发表于 05-25 09:51

    什么原因使外部中断服务函数进不去呢

    ) { EXTI_ClearITPendingBit(EXTI_Line0); GPIO_SetBits(GPIOA , GPIO_Pin_2); }} 这是中断服务函数,我硬件仿真过,进不来为什么外部中断服务函数进不去呢
    发表于 06-18 05:55

    中断SWI怎么使用?

    中断SWI怎么使用?
    发表于 11-16 09:16

    关于RT-Thread中断、调度与死锁的相关知识介绍

    1 中断锁定义中断即为全局中断开关,是禁止多线程访问临界区最简单的一种方式,即通过关闭中断的方式,来保证当前线程不会被其他事件打断(此时系
    发表于 05-25 15:17

    如何利用STM32将文件放到内部flash里去呢

    很多小伙伴在用micropython或者动态模块加载的时候,经常要把文件放到文件系统里面,这个时候有的小伙伴想到了用Ymodem来进行数据传输,当然这是一种方法, 不过这种方法在多文件的时候,就比较
    发表于 09-20 15:38

    CPU中断程序:从硬件看什么是中断

    CPU响应中断转去执行中断服务程序前,需要把中断程序的现场信息保存起来,以便执行完中断服务程序后,接着从被
    发表于 03-26 11:36 214次阅读
    CPU<b class='flag-5'>中断</b>程序:从硬件看什么是<b class='flag-5'>中断</b>?