Home  >  Article  >  Operation and Maintenance  >  What is the role of linux softirqs and work queues

What is the role of linux softirqs and work queues

青灯夜游
青灯夜游Original
2022-04-14 16:41:322571browse

The function of soft interrupts and work queues in Linux is to implement interrupt processing. Soft interrupts and work queues are the lower half implementation mechanisms of the upper and lower interrupt mechanisms. Soft interrupts cannot sleep, block, or switch between processes, and can only be interrupted by hardware interrupts; while the work queue can sleep or be blocked, and can switch between different processes to complete different tasks.

What is the role of linux softirqs and work queues

#The operating environment of this tutorial: linux5.9.8 system, Dell G3 computer.

The function of soft interrupts and work queues in Linux is to implement interrupt processing.

1. Interrupt Concept

Interrupt refers to an interruption during normal operation of the CPU due to internal and external events or by a program The prearranged event causes the CPU to temporarily stop the running program and switch to the program that serves the internal or external event or the prearranged event. After the service is completed, it returns to continue running the temporarily interrupted program. Linux is usually divided into external interrupts (also called hardware interrupts) and internal interrupts (also called exceptions).

In real address mode, the CPU uses the 1KB space starting from 0 in the memory as an interrupt vector table. Each entry in the table occupies 4 bytes. However, in protected mode, the interrupt vector table composed of these 4-byte entries does not meet the actual needs. Therefore, based on the information reflecting the mode switch and the offset, the interrupt vector table entry is made of 8 bytes. The interrupt vector table is also called the interrupt descriptor table (IDT). A register (IDTR) used to describe the interrupt descriptor table is added to the CPU to save the starting address of the interrupt descriptor table.

2. Linux interrupt processing

2.1 System interrupt number

It can be seen from the above interrupt definition , a total of 256 interrupt vector entries can be saved in the system interrupt vector table, is the 256 interrupt descriptors (corresponding to 256 interrupt vectors) contained in the IDT.

 Interrupt vectors 0-31 are reserved by Intel to handle exception events and cannot be used for other purposes. For interrupt vectors No. 0-31, the operating system only needs to provide an exception handler. When an exception occurs, the processor will automatically transfer control to the entry of the corresponding handler and run the corresponding handler; in fact , for these 32 interrupt vectors that handle exceptions, the 2.6 version of Linux only provides handlers for interrupt vectors No. 0-17. For the corresponding handlers, please refer to the following table, interrupt vector and exception event correspondence table; In other words, interrupt vectors No. 17-31 are empty and unused.

##4OverflowOverflow##5 67##8Missing segment interruptSegment_not_presentStack exceptionStack_segmentGeneral protection exception##14Page_fault15 (reserved by intel) 16Coprocessor error17Alignment check interrupt
Interrupt vector number Exception event Linux handler
0 Division error pide_error
1 DebugException Debug
2 NMI Interrupt Nmi
##3 Single byte, int 3 Int3
Boundary Monitoring Interruption Bounds
Invalid Opcode Invalid_op
Device_not_available Device_not_available
Double_fault Double_fault ##9
association Processor segment overrun Coprocessor_segment_overrun 10
Invalid TSS Incalid_tss ##11
12
##13
General_protection
Page_fault
Spurious_interrupt_bug
Coprocessor_error
Alignment_check

Interrupt vectors 0-31 have been reserved, leaving a total of 224 interrupt vectors 32-255 available. How are these 224 interrupt vectors allocated? In 2.6 version of Linux, except 0x80 (SYSCALL_VECTOR) which is used as the system call main entrance, the others are used for external hardware interrupt sources, including 15 irqs of the programmable interrupt controller 8259A; in fact, when CONFIG_X86_IO_APIC is not defined, the other 223 (except 0x80) interrupt vectors only use 15 starting from the 32nd, and the other 208 are left empty.

 2.2 Interrupt request

## 2.2.1 Interrupt request Overview

When external devices require the operating system to do related things, they will generate corresponding interrupts.

The device sends a high level to the interrupt controller through the corresponding interrupt line to generate an interrupt signal, and the operating system will obtain that interrupt line from the status bit of the interrupt controller. interrupts generated. And only when the device has control over a certain interrupt line, it can send a signal to this interrupt line. Also because there are more and more peripherals nowadays, interrupt lines are very precious resources and cannot be mapped one to one. Therefore, before using the interrupt line, you must apply for the corresponding interrupt line. Regardless of whether the shared interrupt method or an exclusive interrupt is used, the application process is to first scan all the interrupt lines to find out which ones are not occupied by others, and select one of them as the IRQ of the device. Secondly, apply for the corresponding IRQ through the interrupt application function. Finally, check whether the interrupt can be executed based on the application result.

 2.2.2 Interrupt related structures

The core processes data during interruption The structure is irq_desc, which completely describes an interrupt line. The source code in Linux 2.6.22.6 is as follows.

## 

irq_desc is defined in include/linux/irq.h

/**
 * struct irq_desc - interrupt descriptor
 *
 * @handle_irq:        highlevel irq-events handler [if NULL, __do_IRQ()]
 * @chip:        low level interrupt hardware access
 * @msi_desc:        MSI descriptor
 * @handler_data:    per-IRQ data for the irq_chip methods
 * @chip_data:        platform-specific per-chip private data for the chip
 *            methods, to allow shared chip implementations
 * @action:        the irq action chain
 * @status:        status information
 * @depth:        disable-depth, for nested irq_disable() calls
 * @wake_depth:        enable depth, for multiple set_irq_wake() callers
 * @irq_count:        stats field to detect stalled irqs
 * @irqs_unhandled:    stats field for spurious unhandled interrupts
 * @lock:        locking for SMP
 * @affinity:        IRQ affinity on SMP
 * @cpu:        cpu index useful for balancing
 * @pending_mask:    pending rebalanced interrupts
 * @dir:        /proc/irq/ procfs entry
 * @affinity_entry:    /proc/irq/smp_affinity procfs entry on SMP
 * @name:        flow handler name for /proc/interrupts output */struct irq_desc {
    irq_flow_handler_t    handle_irq;    struct irq_chip        *chip;    struct msi_desc        *msi_desc;    void            *handler_data;    void            *chip_data;    struct irqaction    *action;    /* IRQ action list */
    unsigned int        status;        /* IRQ status */

    unsigned int        depth;        /* nested irq disables */
    unsigned int        wake_depth;    /* nested wake enables */
    unsigned int        irq_count;    /* For detecting broken IRQs */
    unsigned int        irqs_unhandled;
    spinlock_t        lock;
#ifdef CONFIG_SMP
    cpumask_t        affinity;
    unsigned int        cpu;#endif#if defined(CONFIG_GENERIC_PENDING_IRQ) || defined(CONFIG_IRQBALANCE)
    cpumask_t        pending_mask;#endif#ifdef CONFIG_PROC_FS    struct proc_dir_entry    *dir;#endif
    const char        *name;
} ____cacheline_internodealigned_in_smp;

irq_desc

The associated structures are as follows:

The interrupt action structure defined in include/linux/interrupt.h: struct

irqaction

struct irqaction {
    irq_handler_t handler;
    unsigned long flags;
    cpumask_t mask;    const char *name;    void *dev_id;    struct irqaction *next;    int irq;    struct proc_dir_entry *dir;
};
Defined in include/linux: irq_chip chip-related processing function collection

/**
 * struct irq_chip - hardware interrupt chip descriptor
 *
 * @name:        name for /proc/interrupts
 * @startup:        start up the interrupt (defaults to ->enable if NULL)
 * @shutdown:        shut down the interrupt (defaults to ->disable if NULL)
 * @enable:        enable the interrupt (defaults to chip->unmask if NULL)
 * @disable:        disable the interrupt (defaults to chip->mask if NULL)
 * @ack:        start of a new interrupt
 * @mask:        mask an interrupt source
 * @mask_ack:        ack and mask an interrupt source
 * @unmask:        unmask an interrupt source
 * @eoi:        end of interrupt - chip level
 * @end:        end of interrupt - flow level
 * @set_affinity:    set the CPU affinity on SMP machines
 * @retrigger:        resend an IRQ to the CPU
 * @set_type:        set the flow type (IRQ_TYPE_LEVEL/etc.) of an IRQ
 * @set_wake:        enable/disable power-management wake-on of an IRQ
 *
 * @release:        release function solely used by UML
 * @typename:        obsoleted by name, kept as migration helper */struct irq_chip {    const char    *name;
    unsigned int    (*startup)(unsigned int irq);  //中断开始    void        (*shutdown)(unsigned int irq);    //中断关闭    void        (*enable)(unsigned int irq);      //中断使能    void        (*disable)(unsigned int irq);    //中断禁用    void        (*ack)(unsigned int irq);    void        (*mask)(unsigned int irq);    void        (*mask_ack)(unsigned int irq);    void        (*unmask)(unsigned int irq);    void        (*eoi)(unsigned int irq);    void        (*end)(unsigned int irq);    void        (*set_affinity)(unsigned int irq, cpumask_t dest);    int        (*retrigger)(unsigned int irq);    int        (*set_type)(unsigned int irq, unsigned int flow_type);    int        (*set_wake)(unsigned int irq, unsigned int on);    /* Currently used only by UML, might disappear one day.*/#ifdef CONFIG_IRQ_RELEASE_METHOD    void        (*release)(unsigned int irq, void *dev_id);#endif
    /*
     * For compatibility, ->typename is copied into ->name.
     * Will disappear.     */
    const char    *typename;
};

2.2.3 Interrupt request implementation

Upper and lower half Internal mechanism

We hope to make the interrupt handler run fast, and we want it to complete a large amount of work. These two goals restrict each other. How to solve

——upper and lower half mechanism.

We cut the interrupt handler in half. The interrupt handler is the upper part -

accepts the interrupt, and it starts executing immediately, but it can only do work with a strict time limit. Work that can be allowed to be completed later will be postponed to the second half, and then, at the appropriate time, the second half will be executed by the terminal. The first half is simple and fast, disabling some or all interrupts during execution.

The second half will be executed later, and

can respond to all interrupts during execution. This design can make the system in the interrupt shielding state as short as possible, thereby improving the system's responsiveness. The upper half only has the interrupt handler mechanism, while the lower half has soft interrupt implementation, tasklet implementation and work queue implementation.

We use the network card to explain these two halves. When the network card receives the data packet, it notifies the kernel and triggers an interrupt. The so-called first half is to read the data packet into the memory in time to prevent loss due to delay. This is a very urgent task. After reading the memory, the processing of these data is no longer urgent. At this time, the kernel can execute the program running before the interrupt, and the processing of network data packets is left to the lower half.

Principle of dividing the upper and lower halves

 1)

If a task is very time-sensitive, put it in the interrupt handler implement;

 2) If a task is related to hardware, put it in the interrupt handler for execution;

 3) If a The task must ensure that it is not interrupted by other interrupts and be executed in the interrupt handler;

 4) For all other tasks, consider placing them in the lower half for execution .

Soft interrupt of the lower half implementation mechanism

Soft interrupt, as the representative of the lower half mechanism, is followed by## The emergence of #SMP (share memory processor) came into being, and it is also the basis for the implementation of tasklet (tasklet is actually only used in soft interrupts. A certain mechanism has been added based on this). Softirq is generally the general term for "Delayable function", sometimes including tasklet (readers are asked to infer whether it contains # based on the context when encountering it) ##tasklet). It appears because it needs to satisfy the distinction between the upper and lower halves proposed above, so that tasks that are not time-sensitive can be deferred. The soft interrupt executes the remaining tasks left to it by the interrupt handler, and can Parallel execution on multiple CPU makes the overall system efficiency higher. Its features include: ## a

) cannot be executed immediately after it is generated, and must wait for kernel scheduling before execution. Soft interrupts cannot be interrupted by themselves, but can only be interrupted by hardware interrupts (upper part).

b

) can run concurrently on multiple

CPU (even the same type). Therefore, soft interrupts must be designed as reentrant functions (allowing multiple CPU to operate at the same time), so spin locks also need to be used to protect their data structures.

The tasklet of the lower half implementation mechanism

Tasklet

is implemented through soft interrupts, so it itself is also a soft interrupt.

Soft interrupts are processed in a polling manner. If it happens to be the last type of interrupt, all interrupt types must be cycled before the corresponding processing function can finally be executed. Obviously, in order to ensure the efficiency of polling, the developers limited the number of interrupts to

32

. In order to increase the number of interrupt processing and improve processing efficiency, the

tasklet

mechanism was born.

Tasklet adopts an undifferentiated queue mechanism and is executed only when there is an interruption, eliminating the pain of circular table lookup. TaskletAs a new mechanism, it can obviously bear more advantages. At this time, SMP became more and more popular, so the SMP mechanism was added to tasklet to ensure that the same type of interrupt can only be processed on one cpu Execute on . In the era of soft interrupts, there was obviously no such consideration. Therefore, the same soft interrupt can be executed on two cpu at the same time, which is likely to cause conflicts.

# Summary of the advantages of tasklet:

##  (

1)No limit on the number of types;

 (

2)High efficiency, no need to loop table lookup;## (

3

) Supports SMP mechanism; ## Its characteristics are as follows:

 1) A specific type of

tasklet

can only run on one CPU, and cannot be executed in parallel, but can only be executed serially. 2) Multiple

tasklets

of different types can be run in parallel on multiple CPU on. ## 3) Soft interrupts are statically allocated and cannot be changed after the kernel is compiled. But tasklet

is much more flexible and can be changed at runtime (such as when adding a module).

The lower half of the implementation mechanism is the work queue

The deferrable function we introduced above runs in the interrupt context (one checkpoint of soft interrupt is when do_IRQ exits), which leads to some problems: soft interrupt cannot sleep or block. Since the interrupt context is in the kernel state and there is no process switching, if the soft interrupt is put to sleep or blocked, it will not be able to exit this state, causing the entire kernel to freeze. However, blocking functions cannot be implemented in the interrupt context and must be run in the process context, such as functions that access disk data blocks. Therefore, blocking functions cannot be implemented using softirqs. But they often have deferrable properties.

The deferrable functions we introduced above run in the interrupt context, which causes some problems, indicating that they cannot be suspended, which means that soft interrupts cannot sleep , cannot block. The reason is that the interrupt context is in the kernel state and there is no process switching. Therefore, once the soft interrupt sleeps or is blocked, it will not be able to exit this state, causing the entire kernel to freeze. Therefore, blocking functions cannot be implemented using softirqs. But they often have deferrable properties. And since it is executed serially, as long as one processing time is long, it will cause a delay in the response of other interrupts. In order to complete these impossible tasks, a work queue emerged, which can switch between different processes to complete different tasks.

If the postponed task requires sleep, then choose the work queue. If sleep is not required, then choose soft interrupt or tasklet. Work queues can run in process context and delegate work to a kernel thread. To put it simply, the work queue is a group of kernel threads, used as interrupt daemon threads. Multiple interrupts can be placed in one thread, or each interrupt can be assigned a thread. We use the structure workqueue_struct to represent the worker thread, which is implemented using the kernel thread. And how the worker thread executes the postponed work——There is such a linked list, which consists of the structure work_struct, and this work_struct describes A job, once the job is executed, the corresponding work_struct object is removed from the linked list. When there are no more objects on the linked list, the worker thread will continue to sleep. Because work queues are threads, we can use all the methods that can be used in threads.

#What is the role of soft interrupts and work queues in Linux

The role of soft interrupts and work queues in Linux is to implement interrupt processing; they are the upper and lower interrupt mechanisms The lower half of the implementation mechanism.

 1.Soft interrupt is generally the general name of "Delayable function". It cannot sleep or block. , it is in the interrupt context and cannot switch between processes. Soft interrupts cannot be interrupted by themselves, but can only be interrupted by hardware interrupts (upper part). They can run concurrently on multiple CPU. Therefore, soft interrupts must be designed as reentrant functions, so spin locks are also needed to protect their data structures.

 2.The function in the work queue is in the process context. It can sleep or be blocked, and can switch between different processes to complete different tasks.

Neither the deferrable function nor the work queue can access the user's process space. There cannot be any running process when the deferrable function is executed. The work queue function has While the kernel process is executing, it cannot access user space addresses.

Related recommendations: "

Linux Video Tutorial"

The above is the detailed content of What is the role of linux softirqs and work queues. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Previous article:What is rss in linuxNext article:What is rss in linux