暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

性能篇之CPU软硬中断

小璇坨坨 2019-06-10
1511

进程的不可中断状态是系统的一种保护机制,可以保证硬件的交互过程不被意外打断。所以,短时间的不可中断状态是很正常的。


但是,当进程长时间都处于不可中断状态时,你就得当心了。这时,你可以使用 dstat、pidstat 等工具,确认是不是磁盘 I/O 的问题,进而排查相关的进程和磁盘设备。关于磁盘 I/O 的性能问题,你暂且不用专门去背,我会在后续的 I/O 部分详细介绍,到时候理解了也就记住了。


其实除了 iowait,软中断(softirq)CPU 使用率升高也是最常见的一种性能问题。

中断其实是一种异步的事件处理机制,可以提高系统的并发处理能力

由于中断处理程序会打断其他进程的运行,所以,为了减少对正常进程运行调度的影响,中断处理程序就需要尽可能快地运行。如果中断本身要做的事情不多,那么处理起来也不会有太大问题;但如果中断要处理的事情很多,中断服务程序就有可能要运行很长时间。

特别是,中断处理程序在响应中断时,还会临时关闭中断。这就会导致上一次中断处理完成之前,其他中断都不能响应,也就是说中断有可能会丢失。


软中断

事实上,为了解决中断处理程序执行过长和中断丢失的问题,Linux 将中断处理过程分成了两个阶段,也就是上半部和下半部

上半部用来快速处理中断,它在中断禁止模式下运行,主要处理跟硬件紧密相关的或时间敏感的工作。

下半部用来延迟处理上半部未完成的工作,通常以内核线程的方式运行


网卡接收到数据包后,会通过硬件中断的方式,通知内核有新的数据到了。这时,内核就应该调用中断处理程序来响应它。你可以自己先想一下,这种情况下的上半部和下半部分别负责什么工作呢?

对上半部来说,既然是快速处理,其实就是要把网卡的数据读到内存中,然后更新一下硬件寄存器的状态(表示数据已经读好了),最后再发送一个软中断信号,通知下半部做进一步的处理。

而下半部被软中断信号唤醒后,需要从内存中找到网络数据,再按照网络协议栈,对数据进行逐层解析和处理,直到把它送给应用程序。


所以,这两个阶段你也可以这样理解:

上半部直接处理硬件请求,也就是我们常说的硬中断,特点是快速执行;

而下半部则是由内核触发,也就是我们常说的软中断,特点是延迟执行。

实际上,上半部会打断 CPU 正在执行的任务,然后立即执行中断处理程序。而下半部以内核线程的方式执行,并且每个 CPU 都对应一个软中断内核线程,名字为 “ksoftirqd/CPU 编号”,比如说, 0 号 CPU 对应的软中断内核线程的名字就是 ksoftirqd/0。

不过要注意的是,软中断不只包括了刚刚所讲的硬件设备中断处理程序的下半部,一些内核自定义的事件也属于软中断,比如内核调度和 RCU 锁(Read-Copy Update 的缩写,RCU 是 Linux 内核中最常用的锁之一)等。


查看软中断和内核线程


linux系统的 proc 文件系统。它是一种内核空间和用户空间进行通信的机制,可以用来查看内核的数据结构,或者用来动态修改内核的配置。其中:

    /proc/softirqs 提供了软中断的运行情况;
    /proc/interrupts 提供了硬中断的运行情况。


    运行下面的命令,查看 proc/softirqs 文件的内容,可以看到各种类型软中断在不同 CPU 上的累积运行次数。

      [root@master ~]# cat proc/softirqs 
      CPU0 CPU1 CPU2 CPU3 CPU4 CPU5 CPU6 CPU7 CPU8 CPU9 CPU10 CPU11 CPU12 CPU13 CPU14
      HI: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      TIMER: 96113359 85326741 77969896 73330774 70522303 68018574 65214688 84090784 0 0 0 0 0 0 0
      NET_TX: 44465 2295627 2451766 2175705 2235388 2126982 1866387 21410338 0 0 0 0 0 0 0
      NET_RX: 70961708 66962875 61960523 57727280 55428648 53203176 51005232 110378429 0 0 0 0 0 0 0
      BLOCK: 39 7385 10611 9816 9140 6357 6307 846220 0 0 0 0 0 0 0
      BLOCK_IOPOLL: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      TASKLET: 3300 61771 66054 69608 60031 71439 59730 2187023 0 0 0 0 0 0 0
      SCHED: 64823557 49775960 44065936 41513107 40131203 38759516 37288809 46320093 0 0 0 0 0 0 0
      HRTIMER: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
      RCU: 36208965 33416127 31687573 30599525 29933964 51913806 28593560 32734999 0 0 0 0 0 0 0

      在查看 proc/softirqs 文件内容时,TIMER(定时中断)、NET_RX(网络接收)、SCHED(内核调度)、RCU(RCU 锁)你要特别注意以下这两点。

      第一,要注意软中断的类型,也就是这个界面中第一列的内容。从第一列你可以看到,软中断包括了 10 个类别,分别对应不同的工作类型。比如 NET_RX 表示网络接收中断,而 NET_TX 表示网络发送中断。

      第二,要注意同一种软中断在不同 CPU 上的分布情况,也就是同一行的内容。正常情况下,同一种中断在不同 CPU 上的累积次数应该差不多。比如这个界面中,NET_RX 在 CPU0-7 上的中断次数基本是同一个数量级,相差不大。


      不过你可能发现,TASKLET 在不同 CPU 上的分布并不均匀。TASKLET 是最常用的软中断实现机制,每个 TASKLET 只运行一次就会结束 ,并且只在调用它的函数所在的 CPU 上运行。

      因此,使用 TASKLET 特别简便,当然也会存在一些问题,比如说由于只在一个 CPU 上运行导致的调度不均衡,再比如因为不能在多个 CPU 上并行运行带来了性能限制。

      另外,刚刚提到过,软中断实际上是以内核线程的方式运行的,每个 CPU 都对应一个软中断内核线程,这个软中断内核线程就叫做 ksoftirqd/CPU 编号。那要怎么查看这些线程的运行状况呢?

        [root@master ~]# ps aux | grep softirq
        root 3 0.0 0.0 0 0 ? S May20 0:18 [ksoftirqd/0]
        root 15 0.0 0.0 0 0 ? S May20 0:14 [ksoftirqd/1]
        root 22 0.0 0.0 0 0 ? S May20 0:14 [ksoftirqd/2]
        root 29 0.0 0.0 0 0 ? S May20 0:12 [ksoftirqd/3]
        root 36 0.0 0.0 0 0 ? S May20 0:12 [ksoftirqd/4]
        root 43 0.0 0.0 0 0 ? S May20 0:11 [ksoftirqd/5]
        root 50 0.0 0.0 0 0 ? S May20 0:11 [ksoftirqd/6]
        root 57 0.0 0.0 0 0 ? S May20 0:56 [ksoftirqd/7]
        root 17739 0.0 0.0 112656 2232 pts/0 S+ 22:51 0:00 grep --color=auto softirq

        注意,这些线程的名字外面都有中括号,这说明 ps 无法获取它们的命令行参数(cmline)。一般来说,ps 的输出中,名字括在中括号里的,一般都是内核线程。


        检测中断的性能工具

        这里用到了三个新工具,sar、 hping3 和 tcpdump,先简单介绍一下:

          sar 是一个系统活动报告工具,既可以实时查看系统的当前活动,又可以配置保存和报告历史统计数据。
          hping3 是一个可以构造 TCP/IP 协议数据包的工具,可以对系统进行安全审计、防火墙测试等。
          tcpdump 是一个常用的网络抓包工具,常用来分析各种网络问题。


            [root@bjdfkjy-46-123 ~]# sar -n DEV 1
            Linux 3.10.0-514.el7.x86_64 (bjdfkjy-46-123.qbos.com)   06/10/2019      _x86_64_        (32 CPU)
            11:01:15 PM IFACE rxpck/s txpck/s rxkB/s txkB/s rxcmp/s txcmp/s rxmcst/s
            11:01:16 PM eno1 10.00 6.67 0.93 0.52 0.00 0.00 3.33
            11:01:16 PM eno2 0.00 0.00 0.00 0.00 0.00 0.00 0.00
            11:01:16 PM eno3 0.00 0.00 0.00 0.00 0.00 0.00 0.00
            11:01:16 PM eno4 265.00 228.33 120.59 85.45 0.00 0.00 0.00

            对于 sar 的输出界面,我先来简单介绍一下,从左往右依次是:

            第一列:表示报告的时间。

            第二列:IFACE 表示网卡。

            第三、四列:rxpck/s 和 txpck/s 分别表示每秒接收、发送的网络帧数,也就是 PPS。

            第五、六列:rxkB/s 和 txkB/s 分别表示每秒接收、发送的千字节数,也就是 BPS。

            小结

            Linux 中的中断处理程序分为上半部和下半部:

            上半部对应硬件中断,用来快速处理中断。

            下半部对应软中断,用来异步处理上半部未完成的工作。

            Linux 中的软中断包括网络收发、定时、调度、RCU 锁等各种类型,可以通过查看 /proc/softirqs 来观察软中断的运行情况。


            软中断 CPU 使用率(softirq)升高是一种很常见的性能问题。虽然软中断的类型很多,但实际生产中,我们遇到的性能瓶颈大多是网络收发类型的软中断,特别是网络接收的软中断。

            文章转载自小璇坨坨,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

            评论