软中断和实时性

软中断和实时性

翻译自:Software interrupts and realtime

Linux内核的软中断("softirq")机制有些奇怪,在早期的Linux和处理机制下比较晦涩,且仅有极少的内核开发人员会直接接触软中断。然而它是内核的大多数重要处理的核心。在某些场景下,软中断会以一种不合时宜的方式出现。特别是内核的实时抢占补丁集经常会与软中断产生冲突,该补丁集的最新版本提供了一种解决产生软中断问题的方法,值得一看。

软中断介绍

3.6.1-rt1补丁集的声明中,Thomas Gleixner使用如下方式描述了软中断:

首先,它是大部分不相关任务聚合的产物,运行在随机对任务施加/解除控制的上下文中

First of all,it's a conglomerate of mostly unrelated jobs,which run in the context of a randomly chosen victim w/o the ability to put any control on them.

软中断处理几乎(但不等同)与硬中断一样重要。软中断的优先级比较高(但也有例外,见下文),但低于硬中断,因此会抢占除硬中断外的任何任务。

在很早以前,Linux存在32个硬中断向量,并为每个向量分配一个设备驱动或相关的任务。大部分驱动在很早以前就已经跟软中断分进行了分离(驱动仍然会使用软中断,但需要通过中间APIs,如tasklets和timers)。当前内核中有10种软中断向量:2种用于微线程(tasklet)处理,2种用于网络,2种用于块层(block layer,块设备使用的),2种用于定时器,调度器和read-copy-update(RCU)处理各使用了一种。内核通过CPU位掩码来指定需要处理(任意时间可能发生的)软中断的CPU。例如,当一个内核子系统调用tasklet_schedule()时,会在对应的CPU上设置TASKLET_SOFTIRQ 比特位,当软中断处理完毕后(开中断),会运行微线程 (tasklet基于软中断)

# cat /proc/softirqs
                    CPU0       CPU1
          HI:          1          0				//高优先级的tasklet
       TIMER:  104838818  108267618				//基于系统tick的定时器
      NET_TX:          2          1				//数据发送
      NET_RX:   11622033       2698				//数据接收
       BLOCK:         37    6833945				//块设备访问
BLOCK_IOPOLL:          0          0				//
     TASKLET:          9         46				//普通优先级的tasklet
       SCHED:   61485884   65788587				//多CPU调度
     HRTIMER:          0          0				//高精度定时器
         RCU:   48876416   46889277

有两种情况会引发软中断并抢占当前线程:一种是在处理完一个硬中断时,中断处理程序会触发软中断(硬中断之后会触发软中断,用于处理硬中断的信号或数据,如网卡报文等),为了某些目的(如减小延迟,优化缓存等) 需要尽快处理该软中断,这样就能够重新启用硬中断;另一种是内核代码(在任何时候)可能会(通过调用如local_bh_enable()spin_unlock_bh()函数,这两个函数用于中断保护,防止其他中断混入处理,类似锁机制)重新启用软中断,这样会导致积累的软中断在任意一个进程的上下文中运行,该进程也就是Thomas 所说的"随机挑选的牺牲品"("randomly chosen victim")。

读者可能会对系统上运行的ksoftirqd 感到疑惑,该进程主要用于在系统的软中断负载过高时降低软中断的处理。正规处理中,如果内联的软中断进程代码在循环处理10次之后,发现还需要处理更多的软中断(由于不断产生中断),此时中断进程会唤醒合适的ksoftirqd (每个CPU都有一个ksoftirqd 进程)进程并退出,后续由ksoftirqd 进程处理软中断。Ksoftirqd 可以被(硬件或软件)中断上下文之外的软中断打断,这种处理是必要的,否则Ksoftirqd 在处理下一个软中断前可以运行任意时间。在老的内核中,Ksoftirqd 进程以最低的优先级运行,即对软中断的处理取决于该进程是系统上的最高优先级还是最低优先级。从2.6.23开始,Ksoftirqd默认使用普通用户优先级运行。

实时设置中的软中断

在一般的系统上,软中断机制已经足够处理大部分情况,也不需要做过多改进。然而如The new visibility of RCU processing中描述,在3.7内核中, read-copy-update的任务已经移到其辅助线程中。在实时处理中,强制任意的进程做一些随机工作的方式并不受欢迎,传统的实时补丁会将所有的软中断隔离到独立的线程中,每个线程都有各自的优先级。在这样的处理下,如,当网络需要实时响应时,该中断处理的线程的优先级会提高;相反地,当网络事件不那么紧急时,线程的优先级会降低。

从3.0实时补丁集开始,上面的处理方式无法继续工作。如它无法与Per-CPU variables and the realtime tree很好地配合使用,正如Thomas所说, 采用软中断线程的方式会导致配置问题:

通常很难从一个实时系统中获得合适的参数。将一些像软中断一样晦涩的工作添加到系统设计人员的待做事项中并不是个好主意。

It's extremely hard to get the parameters right for a RT system in general. Adding something which is obscure as soft interrupts to the system designers todo list is a bad idea.

因此,从3.0开始,软中断的处理与主线内核的处理非常类似。使用这种方式改进了代码质量并提升了非协调系统(通过消除切换到软中断线程的上下文)的性能,但也剥夺了倾向于对这种方式进行细微调整的能力(一些专注实时的开发者非常倾向于使用这种方式)。这样也是一些用户对这种改变抱怨的地方。

作为回应,3.6.1-rt1对软中断的处理又作了改动。现在,当一个线程触发一个软中断时,内核会保存特定的中断(如处理接收到的网络报文时)。一旦线程退出,内核会禁用该软中断的上下文,并运行下一个软中断,使用这种方式可以减小处理软中断的延迟(由于会立即运行下一个软中断)。同样重要的是,这种方式将软中断和产生该软中断的进程绑定到了一起。这样产生网络软中断的进程不会陷入处理其他进程的定时器的困境中,使得软中断处理本地化,消除由于处理其他进程的软中断造成的不确定性,并使得软中断能够以一开始创建任务的进程的优先级运行。

但有一种例外:由硬中断引发的软中断不能使用这种方式处理。由于无法将硬中断与一个特定的线程进行关联,因此不能使用对应的线程做必要的处理。这种情况下会将这些软中断交给ksoftirqd 进程处理。

Thomas暗示的下一步处理逻辑为,将一个禁用所有软中断的环境转变为仅禁用特定软中断的环境。大多数禁用软中断的代码仅关心某一特定的软中断处理,其他都允许正常运行。更进一步,Thomas补充到"最好的方式是完全摆脱软中断"。移除软中断机制已经在"待做"列表中存在了很长时间,但没有人实际做这些工作。

实时补丁集的性质使得用户对主线内核的缺陷感到痛苦,这导致来自实时社区的大量主线代码修改和提升。目前,实时用户已经有了一个改进的软中断机制,使其不必再进行底层调优。

TIPS:

  • linux把中断按照等级分为了top half和buttom half,在执行top half的时候是关中断的,而在执行buttom half的时候是开中断的(此时可以再次处理中断)
  • softirq在一个CPU上是串行的,一个tasklet本身就是串行的.softirq性能好,而一个tasklet不考虑在不同CPU上的并行场景,因此其在开发上比较便利。

参考:

Linux中断 - softirq

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


linux常用进程通信方式包括管道(pipe)、有名管道(FIFO)、信号(signal)、消息队列、共享内存、信号量、套接字(socket)。管道用于具有亲缘关系的进程间通信,有名管道的每个管道具有名字,使没有亲缘关系的进程间也可以通信。信号是比较复杂的通信方式,用于通知接受进程有某种事件发生,除
Linux性能观测工具按类别可分为系统级别和进程级别,系统级别对整个系统的性能做统计,而进程级别则具体到进程,为每个进程维护统计信息。

按实现原理分,可分为基于计数器和跟踪以及剖析。含义如下:

计数器:内核维护的统计数据,通常为无符号整型,用于对发生的事件计数,比如,网络包接收计数器,磁
本文详细介绍了curl命令基础和高级用法,包括跳过https的证书验证,详细追踪整个交互过程,可用于调用网络后端接口,诊断http和https网络服务故障。
本文包含作者工作中常用到的一些命令,用于诊断网络、磁盘占满、fd泄漏等问题。命令包括ping、fping、tcpdump、lsof、netstat、/proc/$pid/fd、du、grep、traceroute、dig。
linux的平均负载表示运行态和就绪态及不可中断状态(正在io)的进程数目,用uptime查看到负载很高,既有可能是CPU利用率高,也可能是大量在等待io的进程导致,用mpstat查看每个CPU的使用情况,查看CPU的使用率或者CPU花在等待io的时间,接着用pidstat定位具体的进程
CPU上下文频繁切换会导致系统性能下降,切换分为进程切换、线程切换及中断切换,进程切换的开销较大,除了需要保存寄存器和程序计数器中的值还需保存全局变量、栈等到内存中,以便下次运行恢复,而同一进程中的线程切换开销会小很多,只需更新寄存器和线程独有的栈,共享资源如打开的文件、全局变量等无需切换,当硬件中
1.top命令 作用:该命令可以按CPU使用.内存使用和执行时间对任务进行排序,常用来监控系统中占用CPU或内存较高的程序及CPU和内存的负载。 默认视图: 当想看系统负载时,可观察汇总的%CPU中的us用户进程和sy系统进程是否占用CPU很高,相加接近100%就说明占用很高了,有些程序可能得不到及
文章浏览阅读1.8k次,点赞63次,收藏54次。Linux下的目录权限!!!粘滞位!!!超详解!!!
文章浏览阅读1.6k次,点赞44次,收藏38次。关于Qt的安装、Windows、Linux、MacBook_mack book 安装qt
本文介绍了使用shell脚本编写一个 Hello
文章浏览阅读1.5k次,点赞37次,收藏43次。【Linux】初识Linux——了解操作系统的发展历史以及初次体验Linux编程环境
文章浏览阅读3k次,点赞34次,收藏156次。Linux超详细笔记,个人学习时很认真的记录的,觉得好的麻烦点个赞。
文章浏览阅读6.8k次,点赞109次,收藏114次。【Linux】 OpenSSH_9.3p1 升级到 OpenSSH_9.5p1(亲测无问题,建议收藏)_openssh_9.5p1
文章浏览阅读3.5k次,点赞93次,收藏78次。初识Linux中的线程,理解线程的各种概念,理解进程地址空间中的页表转换,介绍pthread线程库并理解线程库!
文章浏览阅读863次。出现此问题为Linux文件权限问题,解决方案为回到引擎目录执行命令。输入用户密码后运行./UnrealEditor。_increasing per-process limit of core file size to infinity.
文章浏览阅读2.9k次。使用文本编辑器:打开CSV文件,并使用文本编辑器(如Notepad++、Sublime Text、Visual Studio Code等)来查看文件的字符编码格式。通常在编辑器的底部状态栏或设置中可以找到当前编码的显示。请注意,上述方法并非绝对准确,特别是当文件没有明确的编码标识时。因此,如果你发现CSV文件在不同的工具或方法中显示不同的编码格式,可能需要进行进一步的分析和判断,或者尝试使用不同的编码转换方法。该命令将输出文件的MIME类型和编码信息。使用命令行工具:在命令行中,你可以使用。_shell读取csv文件逐行处理
本文介绍了如何在Linux系统中升级gcc版本,以便更好地支持C++11及以上版本的新特性。通过升级gcc,可以提升编译器的功能和性能,获得更好的开发体验。详细的步骤和方法请参考原文链接。
文章浏览阅读4.4k次,点赞6次,收藏19次。Mosquitto是一个开源的MQTT消息代理服务器。MQTT是一个轻量级的、基于发布/订阅模式的消息传输协议。 mosquitto的安装使用比较简单,可以方便的来进行一些测试。_linux mosquitto
文章浏览阅读7.2k次,点赞2次,收藏12次。Linux中,用于根目录下有一个.ssh目录,保存了ssh相关的key和一些记录文件。_~/.ssh/
文章浏览阅读4.5k次,点赞5次,收藏18次。首先需要安装 snmp ,使用下面的命令进行安装安装完毕之后,使用下面的命令查看是否安装成功当命令行显示如图即为安装成功。_snmp工具