Linux (kernel analysis): 24 --- bottom half of interrupt (software interrupt (struct softirq_action, softirq_vec))

First, the soft interrupt Overview

  • Now we begin to discuss the implementation of the bottom half - start with soft interrupt start
  • Soft interrupt use is relatively small. tasklet is more commonly used as a form of the lower half (However, due to the tasklet is achieved by soft interrupt , we'll examine the soft interrupt)
  • Source software interrupt situated kernel / softirq.c file

Second, the soft interrupt implementation

struct softirq_action

  • Soft suspension during compiled statically allocated . It is not tasklet can dynamically register or unregister as
  • A soft interrupt struct softirq_action structure represented, which is defined in <linux / interrupt.h> of:
    • Where the action is a function of the soft interrupt handler (see below softirq_handler)

softirq_vec array

  • kernel / softirq.c defines a package 32 containing an array of the structure
  • Each registered software interrupt occupy one of the array , so there may be up to 32 soft interrupt. Note that this is a fixed value - registered the maximum number of soft interrupt can not be changed dynamically. In the current version of the kernel, which uses only 32 items 9

① soft interrupt handlers (softirq_handler ())

  • Soft interrupt softirq_action structure function is the function of the action , its prototype is as follows:

  • When the time to run a soft kernel interrupt handler, it performs this function , its only parameter a pointer to the corresponding softirq_action structure. For example, if my_softirq point to an array of softirq_vec, the kernel will be used as a way to call the soft interrupt handler function:

  • When you see the whole core structure are passed to the soft interrupt handlers rather than just passing the time value of data, you may be very surprised. This trick can guarantee that in the future when adding a new domain in the structure, without all the soft interrupt handlers were changed. If desired, the soft interrupt handler can easily parse its parameters, to extract value from data member
  • A soft interrupt will not compete with other soft interrupt. In fact, the only way to seize the soft interrupt is an interrupt handler. However, other soft interrupt (or even the same type of software interrupts) can be executed simultaneously on another processor

② soft interrupt register, perform a soft interrupt (do_softirq ())

  • Registration of a software interrupt must only be executed after being tagged . This is known to trigger a soft interrupt . Typically, the interrupt handler will mark its soft interrupt before returning, so that it is executed at a later time. Then, at the appropriate time, the soft suspension will run. In the following places, soft pending interrupt can be checked and executed:
    • From a hardware interrupt code where returns
    • When ksoftirqd kernel thread returns
    • In those explicitly check the code and soft interrupts pending execution, as the network subsystem
  • No matter what way evoke, soft interrupt to be executed in do_softirq () in . This function is very simple. If the soft interrupt is pending, do_softirq () will cycle through each, call them handlers. Let's look at do_softirq () after a simplified core components:

  • The above excerpt is a core part of the soft interrupt processing. It checks and perform all the soft interrupt pending, specifically to do include:
    • 1. pending local variable save local_softirq_pending () Returns the value of the macro. It is a 32-bit bitmap soft interrupt pending - if the n-th bit is set to 1, then the n-th bit corresponds to the type of soft interrupt pending
    • 2. Now the soft interrupt pending bit has been saved, the actual soft interrupt can be cleared in the bitmap
    • 3. The pointer to point h of the first softirq_vec
    • 4. If the pending bit is first set to 1, the h-> action (h) is invoked
    • The second pointer is incremented, so that it now points to the array softirq_vec
    • 6. bit mask pending right one. This will discard first, then let the other you move one position to the right. Thus, the original second place now in the first position on (and so on)
    • 7. Now h pointer points to the second array, the second bit mask is now pending to the first one. Repeat the above steps
    • 8. repeated it, know that pending changes to 0, which indicates that no software has pending interrupts, and our task is finished. Note that this check is sufficient to ensure effective entry point to softirq_vec h total, as may be set pending a maximum of 32, the most it can perform the cycle 32 times

Third, the use of soft interrupt

  • Soft interrupt is reserved for the most demanding of time and most importantly, use the bottom half. Currently, only two subsystems (network and SCSI) directly using soft interrupt. In addition, the kernel timers and tasklet are based on the soft interrupt. If you want to join a new soft interrupt, you should first ask yourself why you can not achieve with tasklet. tasklet can be dynamically generated, because they are less demanding on the lock, it is also very easy to use, and their performance is also very good. Of course, for time-critical and can work efficiently to complete their lock applications, soft interrupt will be the right choice

① Allocation Index

  • During compilation, defined by the <linux / interrupt.h> in an enumerated type statically declare soft interrupt . These core index from 0 to represent one relative priority. Index number of small soft interrupt performed before a large number of soft interrupt index
  • The establishment of a new soft interrupt must add a new entry in this enumeration type. And when you join, you can not like in other places, simply put new items added to the end of the list. Instead, you have to decide where to join in accordance want to give it priority. Traditionally, HI_SOFTIRQ usually as the first, but RCU_SOFTIRQ as the last one . New items may be inserted between BLOCK_SOFTIRQ and TASKLET_SOFTIRQ
  • Subscript include a conventional type tasklet

② Register your handler (open_softirq ())

  • Then, at run-time by registering soft interrupt handler calls open_softirq () , the function takes two parameters: soft interrupt handlers and index number
  • Such as network subsystem, in net / coreldev.c register their software interrupt in the following ways:

  • 软中断处理程序执行的时候,允许相应中断,但它自己不能休眠。在一个处理程序运行的时候 ,当前处理器上的软中断被禁止。但其他的处理器仍可以执行别的软中断。实际上,如果同一个软中断在它被执行的同时再次被触发了,那么另外一个处理器可以同时运行其处理程序。这意味着任何共享数据(甚至是仅在软中断处理程序内部使用的全局变量)都需要严格的锁保护。这点很重要,它也是tasklet更受青睐的原因。单纯地禁止你的软中断处理程序同时执行不是很理想。如果仅仅通过互斥的加锁方式来防止它自身的并发执行,那么使用软中断就没有任何意义了。因此,大部分软中断处理程序,都通过采取单处理器数 (仅属于某一个处理器的数据,因此根本不需要加锁)或其他一些技巧来避免显式地加锁,从而提供更出色的性能
  • 引入软中断的主要原因是其可扩展性。如果不需要扩展到多个处理器,那么,就使用tasklet吧。tasklet本质上也是软中断,只不过同一个处理程序的多个实例不能在多个处理器上同时运行

③触发你的软中断

  • 通过在枚举类型的列表中添加新项以及调用open_softirq()进行注册以后,新的软中断处理程序就能够运行
  • raise_softirq()函数可以将一个软中断设置为挂起状态,让它在下次调用do_softirq()函数时投入运行。举个例子,网络子系统可能会调用:

  • 这会触发NET_TX_SOFTIRQ软中断。它的处理程序net_tx_action()就会在内核下一次执行软中断时投入运行。该函数在触发一个软中断之前先要禁止中断,触发后再恢复原来的状态。如果中断本来就已经被禁止了,那么可以调用另一函数raise_softirq_irqoff,这会带来一些优化效果 。如 :

  • 在中断处理程序中触发软中断是最常见的形式。在这种情况下,中断处理程序执行硬件设备的相关操作,然后触发相应的软中断,最后退出。内核在执行完中断处理程序以后,马上就会调用do_softirq()函数。于是软中断开始执行中断处理程序留给它去完成的剩余任务。在这个例子中,“上半部”和 “下半部”名字的含义一目了然
发布了1326 篇原创文章 · 获赞 851 · 访问量 21万+

Guess you like

Origin blog.csdn.net/qq_41453285/article/details/103996960