精华内容
下载资源
问答
  • 实验内容上交的实验2统一取名为test2) 由父进程创建两个子进程通过终端输入Crtl+\组合键向父进程发送SIGQUIT软中断信号或由系统时钟产生SIGALRM软中断信号发送给父进程父进程接受到这两个软中断的其中某一个后向其两...
  • 使用系统调用fork()创建两个子进程,再用系统调用signal()让父进程捕捉键盘上发出的中断信号(即按delete键),当父进程接收到这两个软中断的某一个后,父进程用系统调用kill()向两个子进程分别发出整数值为16和17...
  • 软中断

    2021-01-15 21:14:56
    最近,某团外卖被爆出大数据杀熟,所谓的大数据杀熟指的是平台利用户的数据,分析你是否是钱多的人,或者是否是不...刹车,大数据杀熟的话题就说到这了,我们还是回归到今日的技术主题:什么是软中断?。 中断是什

    最近,某团外卖被爆出大数据杀熟,所谓的大数据杀熟指的是平台利用户的数据,分析你是否是钱多的人,或者是否是不纠结价格的人,如果是,那么你买同样的物品会比普通用户贵一点,一般这种没有特地去对比价格是很难发现的,所以平台就利用了这点额外赚一些钱。说来很可笑,我们作为平台的资深用户,竟然被平台背后偷偷捞一笔。

    不过,大数据杀熟早已是屡见不鲜的事情了,事实上,几乎所有大平台都存在这种现象,没办法,这就是真实的互联网。

    刹车,大数据杀熟的话题就说到这了,我们还是回归到今日的技术主题:什么是软中断?

    图片


    中断是什么?

    先来看看什么是中断?在计算机中,中断是系统用来响应硬件设备请求的一种机制,操作系统收到硬件的中断请求,会打断正在执行的进程,然后调用内核中的中断处理程序来响应请求。

    这样的解释可能过于学术了,容易云里雾里,我就举个生活中取外卖的例子。

    小林中午搬完砖,肚子饿了,点了份白切鸡外卖,这次我带闪了,没有被某团大数据大熟。虽然平台上会显示配送进度,但是我也不能一直傻傻地盯着呀,时间很宝贵,当然得去干别的事情,等外卖到了配送员会通过「电话」通知我,电话响了,我就会停下手中地事情,去拿外卖。

    这里的打电话,其实就是对应计算机里的中断,没接到电话的时候,我可以做其他的事情,只有接到了电话,也就是发生中断,我才会停下当前的事情,去进行另一个事情,也就是拿外卖。

    从这个例子,我们可以知道,中断是一种异步的事件处理机制,可以提高系统的并发处理能力。

    操作系统收到了中断请求,会打断其他进程的运行,所以中断请求的响应程序,也就是中断处理程序,要尽可能快的执行完,这样可以减少对正常进程运行调度地影响。

    而且,中断处理程序在响应中断时,可能还会「临时关闭中断」,这意味着,如果当前中断处理程序没有执行完之前,系统中其他的中断请求都无法被响应,也就说中断有可能会丢失,所以中断处理程序要短且快。

    还是回到外卖的例子,小林到了晚上又点起了外卖,这次为了犒劳自己,共点了两份外卖,一份小龙虾和一份奶茶,并且是由不同地配送员来配送,那么问题来了,当第一份外卖送到时,配送员给我打了长长的电话,说了一些杂七杂八的事情,比如给个好评等等,但如果这时另一位配送员也想给我打电话。

    很明显,这时第二位配送员因为我在通话中(相当于关闭了中断响应),自然就无法打通我的电话,他可能尝试了几次后就走掉了(相当于丢失了一次中断)。


    什么是软中断?

    前面我们也提到了,中断请求的处理程序应该要短且快,这样才能减少对正常进程运行调度地影响,而且中断处理程序可能会暂时关闭中断,这时如果中断处理程序执行时间过长,可能在还未执行完中断处理程序前,会丢失当前其他设备的中断请求。

    那 Linux 系统为了解决中断处理程序执行过长和中断丢失的问题,将中断过程分成了两个阶段,分别是「上半部和下半部分」

    • 上半部用来快速处理中断,一般会暂时关闭中断请求,主要负责处理跟硬件紧密相关或者时间敏感的事情。

    • 下半部用来延迟处理上半部未完成的工作,一般以「内核线程」的方式运行。

    前面的外卖例子,由于第一个配送员长时间跟我通话,则导致第二位配送员无法拨通我的电话,其实当我接到第一位配送员的电话,可以告诉配送员说我现在下楼,剩下的事情,等我们见面再说(上半部),然后就可以挂断电话,到楼下后,在拿外卖,以及跟配送员说其他的事情(下半部)。

    这样,第一位配送员就不会占用我手机太多时间,当第二位配送员正好过来时,会有很大几率拨通我的电话。

    再举一个计算机中的例子,常见的网卡接收网络包的例子。

    网卡收到网络包后,会通过硬件中断通知内核有新的数据到了,于是内核就会调用对应的中断处理程序来响应该事件,这个事件的处理也是会分成上半部和下半部。

    上部分要做到快速处理,所以只要把网卡的数据读到内存中,然后更新一下硬件寄存器的状态,比如把状态更新为表示数据已经读到内存中的状态值。

    接着,内核会触发一个软中断,把一些处理比较耗时且复杂的事情,交给「软中断处理程序」去做,也就是中断的下半部,其主要是需要从内存中找到网络数据,再按照网络协议栈,对网络数据进行逐层解析和处理,最后把数据送给应用程序。

    所以,中断处理程序的上部分和下半部可以理解为:

    • 上半部直接处理硬件请求,也就是硬中断,主要是负责耗时短的工作,特点是快速执行;

    • 下半部是由内核触发,也就说软中断,主要是负责上半部未完成的工作,通常都是耗时比较长的事情,特点是延迟执行;

    还有一个区别,硬中断(上半部)是会打断 CPU 正在执行的任务,然后立即执行中断处理程序,而软中断(下半部)是以内核线程的方式执行,并且每一个 CPU 都对应一个软中断内核线程,名字通常为「ksoftirqd/CPU 编号」,比如 0 号 CPU 对应的软中断内核线程的名字是 ksoftirqd/0

    不过,软中断不只是包括硬件设备中断处理程序的下半部,一些内核自定义事件也属于软中断,比如内核调度等、RCU 锁(内核里常用的一种锁)等。


    系统里有哪些软中断?

    在 Linux 系统里,我们可以通过查看 /proc/softirqs 的 内容来知晓「软中断」的运行情况,以及 /proc/interrupts 的 内容来知晓「硬中断」的运行情况。

    接下来,就来简单的解析下  /proc/softirqs 文件的内容,在我服务器上查看到的文件内容如下:

    图片

    你可以看到,每一个 CPU 都有自己对应的不同类型软中断的累计运行次数,有 3 点需要注意下。

    第一点,要注意第一列的内容,它是代表着软中断的类型,在我的系统里,软中断包括了 10 个类型,分别对应不同的工作类型,比如 NET_RX 表示网络接收中断,NET_TX 表示网络发送中断、TIMER 表示定时中断、RCU 表示 RCU 锁中断、SCHED 表示内核调度中断。

    第二点,要注意同一种类型的软中断在不同 CPU 的分布情况,正常情况下,同一种中断在不同 CPU 上的累计次数相差不多,比如我的系统里,NET_RX 在 CPU0 、CPU1、CPU2、CPU3 上的中断次数基本是同一个数量级,相差不多。

    第三点,这些数值是系统运行以来的累计中断次数,数值的大小没什么参考意义,但是系统的中断次数的变化速率才是我们要关注的,我们可以使用 watch -d cat /proc/softirqs 命令查看中断次数的变化速率。

    前面提到过,软中断是以内核线程的方式执行的,我们可以用 ps 命令可以查看到,下面这个就是在我的服务器上查到软中断内核线程的结果:

    图片

    可以发现,内核线程的名字外面都有有中括号,这说明 ps 无法获取它们的命令行参数,所以一般来说,名字在中括号里到,都可以认为是内核线程。

    而且,你可以看到有 4 个 ksoftirqd 内核线程,这是因为我这台服务器的 CPU 是 4 核心的,每个 CPU 核心都对应着一个内核线程。


    如何定位软中断 CPU 使用率过高的问题?

    要想知道当前的系统的软中断情况,我们可以使用 top 命令查看,下面是一台服务器上的 top 的数据:

    图片

    上图中的黄色部分 si,就是 CPU 在软中断上的使用率,而且可以发现,每个 CPU 使用率都不高,两个 CPU 的使用率虽然只有 3% 和 4% 左右,但是都是用在软中断上了。

    另外,也可以看到 CPU 使用率最高的进程也是软中断 ksoftirqd,因此可以认为此时系统的开销主要来源于软中断。

    如果要知道是哪种软中断类型导致的,我们可以使用 watch -d cat /proc/softirqs 命令查看每个软中断类型的中断次数的变化速率。

    图片

    一般对于网络 I/O 比较高的 Web 服务器,NET_RX 网络接收中断的变化速率相比其他中断类型快很多。

    如果发现 NET_RX 网络接收中断次数的变化速率过快,接下里就可以使用 sar -n DEV 查看网卡的网络包接收速率情况,然后分析是哪个网卡有大量的网络包进来。

    图片

    接着,在通过 tcpdump 抓包,分析这些包的来源,如果是非法的地址,可以考虑加防火墙,如果是正常流量,则要考虑硬件升级等。


    总结

    为了避免由于中断处理程序执行时间过长,而影响正常进程的调度,Linux 将中断处理程序分为上半部和下半部:

    • 上半部,对应硬中断,由硬件触发中断,用来快速处理中断;

    • 下半部,对应软中断,由内核触发中断,用来异步处理上半部未完成的工作;

    Linux 中的软中断包括网络收发、定时、调度、RCU 锁等各种类型,可以通过查看 /proc/softirqs 来观察软中断的累计中断次数情况,如果要实时查看中断次数的变化率,可以使用 watch -d cat /proc/softirqs 命令。

    每一个 CPU 都有各自的软中断内核线程,我们还可以用 ps 命令来查看内核线程,一般名字在中括号里面到,都认为是内核线程。

    如果在 top 命令发现,CPU 在软中断上的使用率比较高,而且 CPU 使用率最高的进程也是软中断 ksoftirqd 的时候,这种一般可以认为系统的开销被软中断占据了。

    这时我们就可以分析是哪种软中断类型导致的,一般来说都是因为网络接收软中断导致的,如果是的话,可以用 sar 命令查看是哪个网卡的有大量的网络包接收,再用 tcpdump 抓网络包,做进一步分析该网络包的源头是不是非法地址,如果是就需要考虑防火墙增加规则,如果不是,则考虑硬件升级等。

    展开全文
  • 软中断分析

    2019-04-16 18:51:25
    为什么要软中断? 编写驱动的时候,一个中断产生之后,内核在中断处理函数中可能需要完成很多 工作。但是中断处理函数的处理是关闭了中断的。也就是说在响应中断时,系统 不能再次响应外部的其它中断。这样的后果会...
  • 区别有好几点,不过可能我总结得不全面 下面是我自己的一些体会。
  • 操作系统软中断实验

    2018-05-04 16:07:31
    使用系统调用fork()创造二个进程,父进程睡眠2秒后,用系统调用Kill() 向两个子进程发出信号,子进程捕捉到信息后分别输出下列信息终止: Child Processl1 is Killed by Parent! Child Processl2 is Killed by ...
  • 实验六Linux进程间通信24课时 实验目的 理解进程通信原理掌握进程中信号量共享内存消息队列相关的函数的使用 实验原理 Linux下进程通信相关函数除上次实验所用的几个还有 信号量 信号量又称为信号灯它是用来协调不同...
  • 操作系统实验模板,实验环境是linux,实验内容是进程间的软中断通信。
  • 加深对进程概念的理解,明确进程和程序的区别。进一步认识并发执行的实质,并了解Linux系统中进程通信的基本原理。
  • 本文以ARM7内核的LPC2458 MCU,采用软中断的方法实现片外FLASH在运行程序时,同时实现对此FLASH的写操作例程。详细描述了ARM7内核的MCU软中断程序的设计方法。希望能对使用ARM7内核、Cortex-M3/M4内核的MCU,实现...
  • 软中断和硬中断的区别
  • arm裸机软中断

    2018-12-03 13:57:29
    keil5工程。arm裸机实现软中断,实现了64位加法和两个32位数的乘法。
  • 在Linux系统下实现进程间软中断通信和管道通信,只有在捕捉键盘发出的中断信号后,才能打印相关信息。
  • 软中断通信

    2011-10-31 19:57:50
    编制一段程序,使其实现进程的软中断通信。 要求:使用系统调用fork()创建两个子进程,再用系统调用signal()让父进程捕捉键盘上来的中断 信号;当捕捉到中断信号后,父进程用系统调用kill()向两个子进程发出...
  • 硬中断和软中断

    2020-05-12 09:24:50
    硬中断和软中断 一种描述 概述 从本质上来讲,中断是一种电信号,当设备有某种事件发生时,它就会产生中断,通过总线把电信号发送给中断控制器。 如果中断的线是激活的,中断控制器就把电信号发送给处理器的某个...

                                          硬中断和软中断

    一种描述

    概述

    从本质上来讲,中断是一种电信号,当设备有某种事件发生时,它就会产生中断,通过总线把电信号发送给中断控制器。

    如果中断的线是激活的,中断控制器就把电信号发送给处理器的某个特定引脚。处理器于是立即停止自己正在做的事,

    跳到中断处理程序的入口点,进行中断处理。

    (1) 硬中断

    由与系统相连的外设(比如网卡、硬盘)自动产生的。主要是用来通知操作系统系统外设状态的变化。比如当网卡收到数据包

    的时候,就会发出一个中断。我们通常所说的中断指的是硬中断(hardirq)。

    (2) 软中断

    为了满足实时系统的要求,中断处理应该是越快越好。linux为了实现这个特点,当中断发生的时候,硬中断处理那些短时间

    就可以完成的工作,而将那些处理事件比较长的工作,放到中断之后来完成,也就是软中断(softirq)来完成。

    (3) 中断嵌套

    Linux下硬中断是可以嵌套的,但是没有优先级的概念,也就是说任何一个新的中断都可以打断正在执行的中断,但同种中断

    除外。软中断不能嵌套,但相同类型的软中断可以在不同CPU上并行执行。

    (4) 软中断指令

    int是软中断指令。

    中断向量表是中断号和中断处理函数地址的对应表。

    int n - 触发软中断n。相应的中断处理函数的地址为:中断向量表地址 + 4 * n。

    (5)硬中断和软中断的区别

    软中断是执行中断指令产生的,而硬中断是由外设引发的。

    硬中断的中断号是由中断控制器提供的,软中断的中断号由指令直接指出,无需使用中断控制器。

    硬中断是可屏蔽的,软中断不可屏蔽。

    硬中断处理程序要确保它能快速地完成任务,这样程序执行时才不会等待较长时间,称为上半部。

    软中断处理硬中断未完成的工作,是一种推后执行的机制,属于下半部。 
     

    另一种描述

    软中断:


    1、编程异常通常叫做软中断;
    2、软中断是通讯进程之间用来模拟硬中断的 一种信号通讯方式;
    3、 中断源发中断请求或软中断信号后,CPU或接收进程在适当的时机自动进行中断处理或完成软中断信号对应的功能;
    4、软中断是软件实现的中断,也就是程序运行时其他程序对它的中断;而硬中断是硬件实现的中断,是程序运行时设备对它的中断。

    细致化 描述

    1. 软中断的处理非常像硬中断。然而,它们仅仅是由当前正在运行的进程所产生的。

    2. 通常,软中断是一些对I/O的请求。这些请求会调用内核中可以调度I/O发生的程序。对于某些设备,I/O请求需要被立即处理,而磁盘I/O请求通常可以排队并且可以稍后处理。根据I/O模型的不同,进程或许会被挂起直到I/O完成,此时内核调度器就会选择另一个进程去运行。I/O可以在进程之间产生并且调度过程通常和磁盘I/O的方式是相同。

    3. 软中断仅与内核相联系。而内核主要负责对需要运行的任何其他的进程进行调度。一些内核允许设备驱动的一些部分存在于用户空间,并且当需要的时候内核也会调度这个进程去运行。

    4. 软中断并不会直接中断CPU。也只有当前正在运行的代码(或进程)才会产生软中断。这种中断是一种需要内核为正在运行的进程去做一些事情(通常为I/O)的请求。有一个特殊的软中断是Yield调用,它的作用是请求内核调度器去查看是否有一些其他的进程可以运行。

     

    硬中断:


    1、 硬中断是由外部事件引起的因此具有随机性和突发性;软中断是执行中断指令产生的,无面外部施加中断请求信号,因此中断的发生不是随机的而是由程序安排好的;
    2、硬中断的中断响应周期,CPU需要发中断回合信号(NMI不需要),而软中断的中断响应周期,CPU不需发中断回合信号;
    3、硬中断的中断号是由中断控制器提供的(NMI硬中断中断号系统指定为02H);软中断的中断号由指令直接给出,无需使用中断控制器;
    4、硬中断是可屏蔽的(NMI硬中断不可屏蔽),软中断不可屏蔽。

    细致化 描述

    1. 硬中断是由硬件产生的,比如,像磁盘,网卡,键盘,时钟等。每个设备或设备集都有它自己的IRQ(中断请求)。基于IRQ,CPU可以将相应的请求分发到对应的硬件驱动上(注:硬件驱动通常是内核中的一个子程序,而不是一个独立的进程)。

    2. 处理中断的驱动是需要运行在CPU上的,因此,当中断产生的时候,CPU会中断当前正在运行的任务,来处理中断。在有多核心的系统上,一个中断通常只能中断一颗CPU(也有一种特殊的情况,就是在大型主机上是有硬件通道的,它可以在没有主CPU的支持下,可以同时处理多个中断。)。

    3. 硬中断可以直接中断CPU。它会引起内核中相关的代码被触发。对于那些需要花费一些时间去处理的进程,中断代码本身也可以被其他的硬中断中断。

    4. 对于时钟中断,内核调度代码会将当前正在运行的进程挂起,从而让其他的进程来运行。它的存在是为了让调度代码(或称为调度器)可以调度多任务。

     

    区别:
    1、软中断发生的时间是由程序控制的,而硬中断发生的时间是随机的;
    2、软中断是由程序调用发生的,而硬中断是由外设引发的;
    3、硬件中断处理程序要确保它能快速地完成它的任务,这样程序执行时才不会等待较长时间‍。

     

    问题解答:

     1. 问:对于软中断,I/O操作是否是由内核中的I/O设备驱动程序完成?

        答:对于I/O请求,内核会将这项工作分派给合适的内核驱动程序,这个程序会对I/O进行队列化,以可以稍后处理(通常是磁盘I/O),或如果可能可以立即执行它。通常,当对硬中断进行回应的时候,这个队列会被驱动所处理。当一个I/O请求完成的时候,下一个在队列中的I/O请求就会发送到这个设备上

    2. 问:软中断所经过的操作流程是比硬中断的少吗?换句话说,对于软中断就是:进程 ->内核中的设备驱动程序;对于硬中断:硬件->CPU->内核中的设备驱动程序?

    答:是的,软中断比硬中断少了一个硬件发送信号的步骤。产生软中断的进程一定是当前正在运行的进程,因此它们不会中断CPU。但是它们会中断调用代码的流程。

    如果硬件需要CPU去做一些事情,那么这个硬件会使CPU中断当前正在运行的代码。而后CPU会将当前正在运行进程的当前状态放到堆栈(stack)中,以至于之后可以返回继续运行。这种中断可以停止一个正在运行的进程;可以停止正处理另一个中断的内核代码;或者可以停止空闲进程。

     

    参考连接

    https://blog.51cto.com/noican/1361087

    https://vcpu.me/interrupt/

    https://www.jianshu.com/p/52a3ee40ea30

    在这里插入图片描述

    展开全文
  • 除了iowait,软中断(softirq)CPU使用率升高也是最常见的一种性能问题 一、从取外卖看中断 1.1 中断的定义 中断是系统用来响应硬件设备请求的一种机制,它会打断进程的正常调度和执行,然后调用内核中的中断处理程序...

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

    一、从取外卖看中断

    1.1 中断的定义

    中断是系统用来响应硬件设备请求的一种机制,它会打断进程的正常调度和执行,然后调用内核中的中断处理程序来响应设备的请求

    1.2 中断的魅力

    为什么要有中断呢?举个生活中的例子感受一下中断的魅力

    比如订了一份外卖,但是不确定外卖什么时候送到,也没有别的方法了解外卖的进度,但是配送员送外卖是不等人的,到了你这儿没人取的话,就直接走人了。所以你只能苦苦等着,时不时去门口看看外卖送到没,而不能干其他事情

    不过呢,如果在订外卖的时候就跟配送员约定好,让他送到后给你打个电话,那你就不用苦苦等待了,可以去忙别的事情,直到电话一响,接电话、取外卖就可以了

    这里的"打电话"其实就是一个中断
    没接到电话的时候,可以做其他的事情,只有接到了电话(也就是发生中断),才要进行另一个动作:取外卖

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

    1.3 中断处理的时间

    由于中断处理程序会打断其他进程的运行,所以,为了减少对正常进程运行调度的影响,中断处理程序就需要尽可能快地运行

    如果中断本身要做的事情不多,那么处理起来也不会有太大问题,但如果中断要处理的事情很多,中断服务程序就有可能要运行很长时间

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

    1.4 中断丢失

    那么还是以取外卖为例
    假如订了2份外卖,一份主食和一份饮料,并且是由2个不同的配送员来配送
    这次你不用时时等待着,两份外卖都约定了电话取外卖的方式。但是,问题又来了

    当第一份外卖送到时,配送员给你打了个长长的电话,商量发票的处理方式,与此同时,第二个配送员也到了,也想给你打电话

    但是很明显,因为电话占线(也就是关闭了中断响应),第二个配送员的电话是打不通的,所以,第二个配送员很可能试几次后就走掉了(也就是丢失了一次中断)

    二、软中断

    如果弄清楚了"取外卖"的模式,那对系统的中断机制就很容易理解

    2.1 中断处理阶段

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

    • 上半部

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

    • 下半部

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

    2.2 取外卖例子

    比如说前面取外卖的例子:
    上半部就是接听电话,告诉配送员你已经知道了,其他事儿见面再说,然后电话就可以挂断了
    下半部是取外卖的动作,以及见面后商量发票处理的动作

    这样,第一个配送员不会占用你太多时间,当第二个配送员过来时,照样能正常打通你的电话

    2.3 接收数据包例子

    除了取外卖,再举个最常见的网卡接收数据包的例子,更好地理解软中断

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

    • 上半部

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

    • 下半部

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

    2.4 上下部的理解

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

    • 上半部

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

    • 下半部

    由内核触发,也就是我们常说的软中断,特点是延迟执行

    2.5 上下部的执行

    实际上,上下部的处理:

    • 上半部

    打断CPU正在执行的任务,然后立即执行中断处理程序

    • 下半部

    以内核线程的方式执行,并且每个CPU都对应一个软中断内核线程,名字为"ksoftirqd/CPU编号"
    比如:0 号CPU对应的软中断内核线程的名字就是ksoftirqd/0

    注意:
    软中断不只包括了刚刚所讲的硬件设备中断处理程序的下半部,一些内核自定义的事件也属于软中断,比如:

    • 内核调度
    • RCU锁(Read-Copy Update的缩写,RCU是Linux内核中最常用的锁之一)

    2.5 软中断类型

    软中断的类型包括:

    • 网络收发
    • 定时
    • 调度
    • RCU锁

    三、查看软中断和内核线程

    那要怎么知道系统里有哪些软中断呢?

    3.1 proc文件

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

    • /proc/softirqs

    提供了软中断的运行情况

    • /proc/interrupts

    提供了硬中断的运行情况

    3.2 /proc/softirqs文件

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

    $ cat /proc/softirqs
                        CPU0       CPU1
              HI:          0          0
           TIMER:     811613    1972736
          NET_TX:         49          7
          NET_RX:    1136736    1506885
           BLOCK:          0          0
        IRQ_POLL:          0          0
         TASKLET:     304787       3691
           SCHED:     689718    1897539
         HRTIMER:          0          0
             RCU:    1330771    1354737
    

    在查看/proc/softirqs文件内容时,要特别注意以下这两点:

    • 注意软中断的类型

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

    • 注意同一种软中断在不同CPU上的分布情况

    就是同一行的内容
    正常情况下,同一种中断在不同CPU上的累积次数应该差不多
    比如这个界面中,NET_RX在CPU0和CPU1上的中断次数基本是同一个数量级,相差不大

    注意:
    上面的数据中,TASKLET在不同CPU上的分布并不均匀
    TASKLET是最常用的软中断实现机制,每个TASKLET只运行一次就会结束,并且只在调用它的函数所在的CPU上运行
    因此,使用TASKLET特别简便,当然也会存在一些问题,比如说由于只在一个CPU上运行导致的调度不均衡,再比如因为不能在多个CPU上并行运行带来了性能限制

    3.3 查看软中断内核线程

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

    其实用ps命令就可以做到,比如执行下面的指令:

    $ ps aux | grep softirq
    root         7  0.0  0.0      0     0 ?        S    Oct10   0:01 [ksoftirqd/0]
    root        16  0.0  0.0      0     0 ?        S    Oct10   0:01 [ksoftirqd/1]
    

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

    四、软中断性能

    在Linux中,每个CPU都对应一个软中断内核线程,名字是ksoftirqd/CPU编号
    当软中断事件的频率过高时,内核线程也会因为CPU使用率过高而导致软中断处理不及时,进而引发网络收发延迟、调度缓慢等性能问题

    软中断CPU使用率过高也是一种最常见的性能问题

    五、案例

    接下来使用最常见的反向代理服务器Nginx的案例,分析软中断CPU使用率过高的情况

    5.1 分析工具

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

    • sar

    一个系统活动报告工具,既可以实时查看系统的当前活动,又可以配置保存和报告历史统计数据

    • hping3

    一个可以构造TCP/IP协议数据包的工具,可以对系统进行安全审计、防火墙测试等

    • tcpdump

    一个常用的网络抓包工具,常用来分析各种网络问题

    5.2 背景介绍

    在这里插入图片描述
    一台虚拟机运行Nginx,用来模拟待分析的Web服务器
    一台当作Web服务器的客户端,用来给Nginx增加压力请求

    5.3 操作

    安装完成后,在第一个终端执行下面的命令运行案例,启动一个基本的Nginx应用:

    # 运行Nginx服务并对外开放80端口
    $ docker run ‑itd ‑‑name=nginx ‑p 80:80 nginx
    

    然后,在第二个终端使用curl访问Nginx监听的端口,确认Nginx正常启动
    假设192.168.0.30是Nginx所在虚拟机的IP地址,运行curl命令后可以看到下面这个输出界面:

    $ curl http://192.168.0.30/
    <!DOCTYPE html>
    <html>
    <head>
    <title>Welcome to nginx!</title>
    ...
    

    接着,还是在第二个终端,运行hping3命令模拟Nginx的客户端请求:

    # ‑S参数表示设置TCP协议的SYN(同步序列号),‑p表示目的端口为80
    # ‑i u100表示每隔100微秒发送一个网络帧
    # 注:如果你在实践过程中现象不明显,可以尝试把100调小,比如调成10甚至1
    $ hping3 ‑S ‑p 80 ‑i u100 192.168.0.30
    

    现在再回到第一个终端,发现系统响应明显变慢,即便只是在终端中敲几个回车,都得很久才能得到响应?这个时候应该怎么办呢?

    5.4 top资源使用

    那么,该从什么地方入手呢?
    刚才发现,简单的SHELL命令都明显变慢,先看看系统的整体资源使用情况应该是个不错的注意,比如执行下top看看是不是出现了CPU的瓶颈

    在第一个终端运行top命令,看一下系统整体的资源使用情况

    # top运行后按数字1切换到显示所有CPU
    $ top
    top ‑ 10:50:58 up 1 days, 22:10,  1 user,  load average: 0.00, 0.00, 0.00
    Tasks: 122 total,   1 running,  71 sleeping,   0 stopped,   0 zombie
    %Cpu0  :  0.0 us,  0.0 sy,  0.0 ni, 96.7 id,  0.0 wa,  0.0 hi,  3.3 si,  0.0 st
    %Cpu1  :  0.0 us,  0.0 sy,  0.0 ni, 95.6 id,  0.0 wa,  0.0 hi,  4.4 si,  0.0 st
    ...
      PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
        7 root      20   0       0      0      0 S   0.3  0.0   0:01.64 ksoftirqd/0
       16 root      20   0       0      0      0 S   0.3  0.0   0:01.97 ksoftirqd/1
     2663 root      20   0  923480  28292  13996 S   0.3  0.3   4:58.66 docker‑containe
     3699 root      20   0       0      0      0 I   0.3  0.0   0:00.13 kworker/u4:0
     3708 root      20   0   44572   4176   3512 R   0.3  0.1   0:00.07 top
        1 root      20   0  225384   9136   6724 S   0.0  0.1   0:23.25 systemd
        2 root      20   0       0      0      0 S   0.0  0.0   0:00.03 kthreadd
    ...
    

    从第一行开始,逐个看一下:

    1. 平均负载全是0,就绪队列里面只有一个进程(1 running)
    2. 每个CPU的使用率都挺低,最高的CPU1的使用率也只有4.4%
    3. 查看进程列表,CPU使用率最高的进程只有0.3%

    那为什么系统的响应变慢了呢?
    既然每个指标的数值都不大,那就再来看看,这些指标对应的更具体的含义。毕竟,哪怕是同一个指标,用在系统的不同部位和场景上,都有可能对应着不同的性能问题

    仔细看top的输出,两个CPU的使用率虽然分别只有3.3%和4.4%,但都用在了软中断上
    而从进程列表上也可以看到,CPU使用率最高的也是软中断进程ksoftirqd。看起来,软中断有点可疑了

    5.5 判断软中断类型

    既然软中断可能有问题,那先要知道究竟是哪类软中断的问题
    使用proc文件系统判断软中断类型呢?观察/proc/softirqs文件的内容,可以知道各种软中断类型的次数

    不过,这里的各类软中断次数,又是什么时间段里的次数呢?它是系统运行以来的累积中断次数

    5.6 软中断变化情况

    直接查看文件内容,得到的只是累积中断次数,对这里的问题并没有直接参考意义,因为这些中断次数的变化速率才是需要关注的

    那什么工具可以观察命令输出的变化情况呢?
    watch命令可以定期运行一个命令来查看输出,如果再加上-d参数,还可以高亮出变化的部分,从高亮部分可以直观看出哪些内容变化得更快

    还是在第一个终端,运行下面的命令:

    $ watch ‑d cat /proc/softirqs
                        CPU0       CPU1
              HI:          0          0
           TIMER:    1083906    2368646
          NET_TX:         53          9
          NET_RX:    1550643    1916776
           BLOCK:          0          0
        IRQ_POLL:          0          0
         TASKLET:     333637       3930
           SCHED:     963675    2293171
         HRTIMER:          0          0
             RCU:    1542111    1590625
    

    通过/proc/softirqs文件内容的变化情况,TIMER(定时中断)、NET_RX(网络接收)、SCHED(内核调度)、RCU(RCU锁)等这几个软中断都在不停变化

    其中,NET_RX也就是网络数据包接收软中断的变化速率最快。而其他几种类型的软中断,是保证Linux 调度、时钟和临界区保护这些正常工作所必需的,所以它们有一定的变化倒是正常的

    5.7 sar观察系统网络接收情况

    那么接下来,就从网络接收的软中断着手继续分析
    既然是网络接收的软中断,第一步应该就是观察系统的网络接收情况,接下来使用网络工具sar

    sar可以用来查看系统的网络收发情况,还有一个好处是不仅可以观察网络收发的吞吐量(BPS,每秒收发的字节数),还可以观察网络收发的PPS,即每秒收发的网络帧数

    在第一个终端中运行sar命令,并添加-n DEV参数显示网络收发的报告:

    # ‑n DEV 表示显示网络收发的报告,间隔1秒输出一组数据
    $ sar ‑n DEV 1
    15:03:46        IFACE   rxpck/s   txpck/s    rxkB/s    txkB/s   rxcmp/s   txcmp/s  rxmcst/s   %ifutil
    15:03:47         eth0  12607.00   6304.00    664.86    358.11      0.00      0.00      0.00      0.01
    15:03:47      docker0   6302.00  12604.00    270.79    664.66      0.00      0.00      0.00      0.00
    15:03:47           lo      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00
    15:03:47    veth9f6bbcd   6302.00  12604.00    356.95    664.66      0.00      0.00      0.00      0.
    

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

    • 第一列

    表示报告的时间

    • 第二列

    IFACE 表示网卡

    • 第三、四列

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

    • 第五、六列

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

    后面的其他参数基本接近0,显然跟上面的问题没有直接关系,可以先忽略掉

    具体看输出的内容,可以发现:

    • 网卡eth0

    每秒接收的网络帧数比较大,达到了12607,而发送的网络帧数则比较小,只有6304;每秒接收的千字节数只有664 KB,而发送的千字节数更小,只有358 KB

    • docker0和veth9f6bbcd

    数据跟eth0基本一致,只是发送和接收相反,发送的数据较大而接收的数据较小
    Linux内部网桥转发导致,系统把eth0收到的包转发给Nginx服务

    5.8 数据包大小分析

    从这些数据,有没有发现什么异常的地方?

    既然怀疑是网络接收中断的问题,还是重点来看eth0 :
    接收的PPS比较大,达到12607,而接收的BPS却很小,只有664KB,直观来看网络帧应该都是比较小,计算一下,664*1024/12607 = 54字节,说明平均每个网络帧只有54字节,这显然是很小的网络帧,也就是我们通常所说的小包问题

    5.9 tcpdump抓包分析

    那么,有没有办法知道这是一个什么样的网络帧,以及从哪里发过来的呢?
    使用tcpdump抓取eth0上的包就可以了,事先已经知道Nginx监听在 80 端口,它所提供的HTTP 服务是基于TCP协议,所以可以指定TCP协议和80端口精确抓包

    接下来,在第一个终端中运行tcpdump命令,通过-i eth0选项指定网卡eth0,并通过tcp port 80选项指定TCP协议的80端口:

    # ‑i eth0 只抓取eth0网卡,‑n不解析协议名和主机名
    # tcp port 80表示只抓取tcp协议并且端口号为80的网络帧
    $ tcpdump ‑i eth0 ‑n tcp port 80
    15:11:32.678966 IP 192.168.0.2.18238 > 192.168.0.30.80: Flags [S], seq 458303614, win 512, length 0
    ...
    

    从tcpdump的输出中,可以发现:

    192.168.0.2.18238 > 192.168.0.30.80,表示网络帧从192.168.0.2的18238端口发送到192.168.0.30的80端口,也就是从运行hping3机器的18238端口发送网络帧,目的为Nginx所在机器的80端口,Flags [S]则表示这是一个SYN包

    5.10 SYN FLOOD攻击

    再加上前面用sar发现,PPS超过12000的现象,现在可以确认这就是从192.168.0.2这个地址发送过来的SYN FLOOD攻击

    到这里,已经做了全套的性能诊断和分析
    从系统的软中断使用率高这个现象出发,通过观察/proc/softirqs文件的变化情况,判断出软中断类型是网络接收中断,再通过sar和tcpdump,确认这是一个SYN FLOOD问题

    SYN FLOOD问题最简单的解决方法,就是从交换机或者硬件防火墙中封掉来源IP,这样SYN FLOOD网络帧就不会发送到服务器中

    六、小结

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

    • 上半部对应硬件中断,用来快速处理中断
    • 下半部对应软中断,用来异步处理上半部未完成的工作

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

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

    在碰到这类问题时,可以借用sar、tcpdump等工具,做进一步分析

    展开全文
  • Linux 软中断机制分析

    万次阅读 多人点赞 2018-09-12 11:57:37
    软中断分析  最近工作繁忙,没有时间总结内核相关的一些东西。上次更新博客到了linux内核中断子系统。这次总结一下软中断,也就是softirq。之后还会总结一些tasklet、工作队列机制。 1. 为什么要软中断  编写...

    软中断分析

        最近工作繁忙,没有时间总结内核相关的一些东西。上次更新博客到了linux内核中断子系统。这次总结一下软中断,也就是softirq。之后还会总结一些tasklet、工作队列机制。

    1. 为什么要软中断

        编写驱动的时候,一个中断产生之后,内核在中断处理函数中可能需要完成很多工作。但是中断处理函数的处理是关闭了中断的。也就是说在响应中断时,系统不能再次响应外部的其它中断。这样的后果会造成有可能丢失外部中断。于是,linux内核设计出了一种架构,中断函数需要处理的任务分为两部分,一部分在中断处理函数中执行,这时系统关闭中断。另外一部分在软件中断中执行,这个时候开启中断,系统可以响应外部中断。

        关于软件中断的理论各种书籍都有介绍,不多叙述。而要真正体会软件中断的作用就必须从代码的角度来分析。我们做工作时候讲求的是professional,当一个人在某个领域一无所知的时候,我们称他为小白,偶,非苹果电脑。小白的脑子里充满了各种问题。慢慢的当这些疑惑解释完之后,小白就脱白了。此时,我们对这个领域的基本框架有了解,但这和professional还有一定的差距。再加以时日,逐渐融会贯通该领域才能达到专业的境界。

    2. 什么时候触发处理软件中断

        说了这么多废话,赶快步入正题。初识软中断,脑子里肯定有不少的疑问,首先就是软件中断在什么地方被触发处理?这个问题的答案就是:一个硬件中断处理完成之后。下面的函数在处理完硬件中断之后推出中断处理函数,在irq_exit中会触发软件中断的处理。

    
    asmlinkage void __exception asm_do_IRQ(unsigned int irq, structpt_regs *regs) 
    { 
        struct pt_regs *old_regs = set_irq_regs(regs); 
      
        irq_enter(); 
      
        /* 
         * Some hardware gives randomly wrong interrupts.  Rather 
         * than crashing, do something sensible. 
         */  
        if (irq >= NR_IRQS) 
            handle_bad_irq(irq, &bad_irq_desc); 
        else  
            generic_handle_irq(irq); 
      
        /* AT91 specific workaround */  
        irq_finish(irq); 
      
        irq_exit(); 
        set_irq_regs(old_regs); 
    }

        这里要注意,invoke_softirq必须满足两个条件才能被调用到,一个就是不是在硬件中断处理过程中或者在软件中断处理中,第二个就是必须有软件中断处于pending状态。第二个好理解,有软件中断产生才去处理,没有就不处理。第一个就不好理解了。

    /* 
    * Exit an interrupt context. Process softirqs if needed and possible:
    */  
    void irq_exit(void) 
    { 
        account_system_vtime(current); 
        trace_hardirq_exit(); 
        sub_preempt_count(IRQ_EXIT_OFFSET); 
        if (!in_interrupt() && local_softirq_pending()) 
            invoke_softirq(); 
      
    #ifdef CONFIG_NO_HZ 
        /* Make sure that timer wheel updates are propagated */  
        rcu_irq_exit(); 
        if (idle_cpu(smp_processor_id()) && !in_interrupt() && !need_resched()) 
            tick_nohz_stop_sched_tick(0); 
    #endif  
        preempt_enable_no_resched(); 
    }

    在linux系统的进程数据结构里,有这么一个数据结构

    #define preempt_count() (current_thread_info()->preempt_count),

    利用preempt_count可以表示是否处于中断处理或者软件中断处理过程中。

    
    #define PREEMPT_MASK    (__IRQ_MASK(PREEMPT_BITS) << PREEMPT_SHIFT) 
    #define SOFTIRQ_MASK    (__IRQ_MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT) 
    #define HARDIRQ_MASK    (__IRQ_MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT) 
      
    #define PREEMPT_OFFSET    (1UL << PREEMPT_SHIFT) 
    #define SOFTIRQ_OFFSET    (1UL << SOFTIRQ_SHIFT) 
    #define HARDIRQ_OFFSET    (1UL << HARDIRQ_SHIFT)

    sub_preempt_count(IRQ_EXIT_OFFSET);

    #define in_interrupt() (irq_count())

    #define irq_count() (preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK))

                         wps_clip_image-31524 

        preempt_count的8~23位记录中断处理和软件中断处理过程的计数。如果有计数,表示系统在硬件中断或者软件中断处理过程中。系统这么设计是为了避免软件中断在中断嵌套中被调用,并且达到在单个CPU上软件中断不能被重入的目的。对于ARM架构的CPU不存在中断嵌套中调用软件中断的问题,因为ARM架构的CPU在处理硬件中断的过程中是关闭掉中断的。只有在进入了软中断处理过程中之后才会开启硬件中断,如果在软件中断处理过程中有硬件中断嵌套,也不会再次调用软中断,because硬件中断是软件中断处理过程中再次进入的,此时preempt_count已经记录了软件中断!对于其它架构的CPU,有可能在触发调用软件中断前,也就是还在处理硬件中断的时候,就已经开启了硬件中断,可能会发生中断嵌套,在中断嵌套中是不允许调用软件中断处理的。Why?我的理解是,在发生中断嵌套的时候,表明这个时候是系统突发繁忙的时候,内核第一要务就是赶紧把中断中的事情处理完成,退出中断嵌套。避免多次嵌套,哪里有时间处理软件中断,所以把软件中断推迟到了所有中断处理完成的时候才能触发软件中断。

    3. 软件中断的处理过程

        之前我已经说到,软中断的一个很大的目的就是避免中断处理中,处理的操作过多而丢失中断。同时中断还需要考虑到一件事情就是中断处理过程过长就会影响系统响应时间。如果一个中断处理一秒钟,那你一定能感受到串口卡住的现象。从另外一方面说呢,我们又必须考虑中断处理的操作一定的优先度,毕竟是硬件触发的事务,关系到网络、块设备的效率问题。Linux内核就中断方面就必须考虑平衡这三个方面的问题。而下面我要分析的__do_softirq函数就恰似在这三者之间打太极,游刃有余,面面俱到!

     /* 
    * We restart softirq processing MAX_SOFTIRQ_RESTART times, 
    * and we fall back to softirqd after that. 
    * 
    * This number has been established via experimentation. 
    * The two things to balance is latency against fairness - 
    * we want to handle softirqs as soon as possible, but they 
    * should not be able to lock up the box. 
    */  
    #define MAX_SOFTIRQ_RESTART 10  
      
    asmlinkage void __do_softirq(void) 
    { 
        struct softirq_action *h; 
        __u32 pending; 
        int max_restart = MAX_SOFTIRQ_RESTART; 
        int cpu; 
      
        pending = local_softirq_pending(); 
        account_system_vtime(current); 
      
        __local_bh_disable((unsigned long)__builtin_return_address(0)); 
        trace_softirq_enter(); 
      
        cpu = smp_processor_id(); 
    restart: 
        /* Reset the pending bitmask before enabling irqs */  
        set_softirq_pending(0); 
      
        local_irq_enable(); 
      
        h = softirq_vec; 
      
        do  
        { 
            if (pending & 1) 
            { 
                int prev_count = preempt_count(); 
      
                h->action(h); 
      
                if (unlikely(prev_count != preempt_count())) 
                { 
                    printk(KERN_ERR "huh, entered softirq %td %p"  
                           "with preempt_count %08x,"  
                           " exited with %08x?\n", h - softirq_vec, 
                           h->action, prev_count, preempt_count()); 
                    preempt_count() = prev_count; 
                } 
      
                rcu_bh_qsctr_inc(cpu); 
            } 
            h++; 
            pending >>= 1; 
        } 
        while (pending); 
      
        local_irq_disable(); 
      
        pending = local_softirq_pending(); 
        if (pending && --max_restart) 
            goto restart; 
      
        if (pending) 
            wakeup_softirqd(); 
      
        trace_softirq_exit(); 
      
        account_system_vtime(current); 
        _local_bh_enable(); 
    }
    
    

     __do_softirq函数处理软件中断过程如下图流程分析

    4. 首先调用local_softirq_pending函数取得目前有哪些位存在软件中断

    5. 调用__local_bh_disable关闭软中断,其实就是设置正在处理软件中断标记,在同一个CPU上使得不能重入__do_softirq函数

    6. 重新设置软中断标记为0,set_softirq_pending重新设置软中断标记为0,这样在之后重新开启中断之后硬件中断中又可以设置软件中断位。

    7. 开启硬件中断

    8. 之后在一个循环中,遍历pending标志的每一位,如果这一位设置就会调用软件中断的处理函数。在这个过程中硬件中断是开启的,随时可以打断软件中断。这样保证硬件中断不会丢失。

    9. 之后关闭硬件中断,查看是否又有软件中断处于pending状态,如果是,并且在本次调用__do_softirq函数过程中没有累计重复进入软件中断处理的次数超过10次,就可以重新调用软件中断处理。如果超过了10次,就调用wakeup_softirqd();唤醒内核的一个进程来处理软件中断。设立10次的限制,也是为了避免影响系统响应时间。

                                                   wps_clip_image-25966

    4. 处理软中断内核线程

        之前我说到不能让CPU长时间来处理中断事务,这样会影响系统的响应时间,严重影响用户和系统之间的交互式体验。所以在之前的__do_softirq中最多将循环执行10次,那么当执行了10次仍然有软中断在pending状态,这个时候应该怎么处理呢?系统将唤醒一个软件中断处理的内核进程,在内核进程中处理pending中的软件中断。这里要注意,之前我们分析的触发软件中断的位置其实是中断上下文中,而在软中断的内核线程中实际已经是进程的上下文。

    这里说的软中断上下文指的就是系统为每个CPU建立的ksoftirqd进程。

     

        看完这个函数,我不得不佩服这个函数设计的精巧!而我更多的从中体会到其中蕴藏的一种做人的道理。那就是做人要霸道一点,太谦和太恭维不行,但是又不能横行霸道,原则的问题要公平讲理,一定的时候顾及别人的利益,好处不能一个人独吞。这就跟下面ksoftirqd处理过程一样,该狠的时候禁止抢占,其它进程别想调度到哦,但是自己占用CPU时间过长的话,也自觉的问一问是不是该释放CPU给其它进程了。

        下面我们就来分析一下这个处理过程怎么就体现了上面的这种说法呢?软中断的内核进程中主要有两个大循环,外层的循环处理有软件中断就处理,没有软件中断就休眠。内层的循环处理软件中断,并每循环一次都试探一次是否过长时间占据了CPU,需要调度释放CPU给其它进程。具体的操作在注释中做了解释。

    
    static int ksoftirqd(void *__bind_cpu) 
    { 
        set_current_state(TASK_INTERRUPTIBLE); 
      
        while (!kthread_should_stop()) 
        { 
            /*不管三七二十一首先禁止抢占,我掌握CPU,并全凭我自己掌握调度*/  
            preempt_disable(); 
            if (!local_softirq_pending()) 
            { 
                preempt_enable_no_resched(); 
                /*如果没有软中断在pending,那就让出CPU来吧*/  
                schedule(); 
               /*我被唤醒了,首先掌握CPU,不让自己被抢占,自己决定自己的是否要调度*/  
                preempt_disable(); 
            } 
      
            __set_current_state(TASK_RUNNING); 
      
            while (local_softirq_pending()) 
            { 
                /* Preempt disable stops cpu going offline. 
                   If already offline, we'll be on wrong CPU: 
                   don't process */  
                if (cpu_is_offline((long)__bind_cpu)) 
                    goto wait_to_die; 
                /*处理软中断*/  
                do_softirq(); 
                /*虽然我自己掌握是否要调度,虽然我可以一直不调度,但是我是 
                个正直的人,运行一段时间后我会看看是否需要调度,还其它进程运行*/  
                preempt_enable_no_resched(); 
                cond_resched(); 
                preempt_disable(); 
                rcu_qsctr_inc((long)__bind_cpu); 
            } 
            preempt_enable(); 
            set_current_state(TASK_INTERRUPTIBLE); 
        } 
        __set_current_state(TASK_RUNNING); 
        return 0; 
      
    wait_to_die: 
        preempt_enable(); 
        /* Wait for kthread_stop */  
        set_current_state(TASK_INTERRUPTIBLE); 
        while (!kthread_should_stop()) 
        { 
            schedule(); 
            set_current_state(TASK_INTERRUPTIBLE); 
        } 
        __set_current_state(TASK_RUNNING); 
        return 0; 
    } 
    

     

    文章内容转载自:http://blog.chinaunix.net/uid-28236237-id-3450751.html

     

     

    展开全文
  •  进程的软中断通信 2[实验目的]  (1)理解掌握软中断的概念和技术;  (2)掌握进程之间基于软中断的通信技术。 3[实验内容]  编写一段程序,父进程创建一个子进程p1;并使子进程利用系统调用kill()向...
  • 从本质上来讲,中断是一种电信号,当设备有某种事件发生时,它就会产生中断,通过总线把电信号发送给中断控制器(如 8259A)。 如果中断的线是激活的,中断控制器就把电信号发送给处理器的某个特定引脚。处理器于是...
  • Linux 中的软中断包括网络收发、定时、调度、RCU锁等各种类型,我们可以查看proc 文件系统中的/proc/softirqs,观察软中断的运行情况。 在Linux中,每个CPU都对应一个软中断内核线程,名字是 ksofirqd/CPU编号。当...
  • 1. 怎么去理解 前面博客简单说过中断的含义,中断是系统...由于中断处理程序会打断进程的运行,特别是还会临时关闭中断,会导致上一次中断处理程序完成以前,其他中断都不能响应,那么这种情况下中断也可能会丢失,...
  • 中断 中断指当出现需要时,CPU暂时停止当前程序的执行转而执行处理新情况的程序和执行过程。即在程序运行过程中,系统出现了一个必须由CPU立即处理的情况,此时,CPU暂时中止程序的执行转而处理这个新的情况的过程就...
  • 1、简介 2、中断处理 3、软中断
  • Linux进程的软中断通信(signal和kill)

    千次阅读 多人点赞 2020-11-14 22:48:04
    Linux的进程软中断通信一、软中断信号二、函数介绍(1)wait函数(2)signal函数(3)sleep函数(4)kill函数三、示例 一、软中断信号 软中断信号(signalsignalsignal,又简称为信号)用来通知进程发生了事件。进程...
  • 进程的软中断通信

    2012-12-17 09:25:52
    用fork()创建两个子进程,再用系统调用signal()让父进程捕捉键盘上来的中断信号(即按Ctrl+C键);捕捉到中断信号后,父进程用系统调用kill()向两个子进程发出信号,子进程捕捉到信号后分别输出下列信息后终止: ...
  • 硬中断与软中断区别

    万次阅读 多人点赞 2018-01-21 15:43:56
    转自:http://blog.csdn.net/yxfabcdefg/article/details/53127155 http://blog.csdn.net/qq_29350001/article/details/52118662中断上半部分与中断下半部分对比在中断...鉴于这两个目的不可调和的矛盾,中断处理...
  • 中断从硬件到内核的路由 概念 从物理学的角度看,中断是一种电信号,由硬件设备生成,并直接送入中断控制器的输入引脚上。 然后再由中断控制器向处理器发送相应的信号。处理器一经检测到此信号,便中断自己的当前...
  • ARM 软中断指令SWI

    千次阅读 2018-12-29 21:40:06
    前面我们学习ARM工作模式中,处理器模式切换可以通过软件控制进行切换,即修改CPSR模式位...若想实现模式切换,只能由另一种方法来实现,即通过外部中断或是异常处理过程进行切换。于是ARM指令集中提供了两条产生异...
  • 软中断 软中断(softirq)是中断处理程序在开启中断的情况下执行的部分,可以被硬中断抢占。 内核定义了一张软中断向量表,每种软中断有一个唯一的编号,对应一个softirq_action实例,softirq_action实例的成员...
  • CPU软中断概念与案例

    2020-04-03 22:47:53
    CPU软中断概念&案例 1 案例一 1.1 环境部署 环境1:WEB服务器 docker run -itd --name=nginx -p 80:80 nginx 环境2:SYN攻击 curl http://xxx.xxx.xxx.xxx/ <!DOCTYPE html> <html> <head> &...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 91,432
精华内容 36,572
关键字:

软中断