zoukankan      html  css  js  c++  java
  • 记一个实时Linux的中断线程化问题

    背景

    有一个项目对实时性要求比较高,于是在linux内核上打了RT_PREEMPT补丁。

    最终碰到的一个问题是,芯片本身性能不强,CPU资源不足,急需优化。

    初步分析

    看了下cpu占用率,除了主应用之外,有一个名为irq/38-twi0的进程引起了我们的注意,因为它竟然占据了10%的cpu。

    这个irq开头的进程是做什么的呢?原来这是一个被线程化了的中断服务程序,负责处理i2c中断的。这个项目i2c总线上挂载了多个设备,压力是比较大的。

    第一个想法是能否减少设备数量或者减低采集频率,但这会影响到应用的算法表现,暂时不考虑。

    第二个想法是优化代码,但打开中断服务程序的源码一看,其实现非常简单,基本就只是从硬件寄存器中把接收到的数据取出来而已,看来从这里入手也希望不大。

    再仔细想想,这个进程执行的操作这么简单,CPU占用率却这么高,那么主要就是因为其执行的频率过高,每次执行其实都会伴随着进程调度/上下文切换带来的开销,这部分是否可以进行优化呢。

    中断线程化回顾

    让我们来回顾下中断线程化的知识。

    在Linux上,中断的优先级比进程高,一旦中断过来普通进程实时进程通通都要让路,让CPU先运行对应的中断处理程序,这就会对实时性造成很大的影响。

    为了解决这个由中断带来的实时性问题,或者说由不确定运行时长的中断服务程序带来的实时性问题,RT_PREEMPT补丁引入了中断线程化的机制。

    中断线程化之后,中断来了虽然还是会打断实时进程,但所执行的操作只是唤醒中断线程,原本的中断服务程序被放到了一个内核线程中,延迟执行。

    这样中断执行的速度就很快也很有确定性,实时进程被打断后可以迅速再次运行,至于中断服务程序,就在优先满足实时进程的情况下,再被调度执行。

    从中断线程化的初衷看,当前这种情况根本就不适用。

    1.这个中断服务程序非常简单,没必要线程化。强行线程化对实时性的改善不大,反而会带来不必要的开销。

    2.这个中断服务程序非常关键,其中采集的数据的实时性也非常重要,不应该被延迟执行。中断切换回实时进程后,实时进程依赖这些数据,还是要等这个进程把数据取出。

    解决

    解决方式很简单,对于这个具体的中断,取消线程化,让它变回一个朴素的中断。中断线程化的机制虽好,也要分情况来使用,不然反而会造成系统的巨大负担。

    代码改动是在request_irq时,传入IRQF_NO_THREAD标志,即可避免这个中断被线程化。

    实际做改动还要注意,RT_PREEMPT使用rt_mutex代替传统的禁用抢占的spin_lock,因此如果需要用真正的spin_lock,需要使用raw_spin_lock_t

    在这个具体的例子中,中断大概为一万两千次/秒,取消线程化之后,CPU占用率下降了约10%,效果显著。

    本文地址:https://www.cnblogs.com/zqb-all/p/12229990.html

    欢迎点击扫码关注公众号: QB杂货铺

  • 相关阅读:
    在SQLite中使用索引优化查询速度
    SQLite支持的SQL数据操作
    left (outer) join , right (outer) join, full (outer) join, (inner) join, cross join 区别
    深入理解Android内存管理原理(六)
    Merge Sorted Array
    Sort Colors
    Construct Binary Tree from Preorder and Inorder Traversal
    Binary Tree Postorder Traversal
    Symmetric Tree
    Rotate Image
  • 原文地址:https://www.cnblogs.com/zqb-all/p/12229990.html
Copyright © 2011-2022 走看看