One for engineering students , Keen on the underlying technology development , Have a strong curiosity , I'm interested in MCU , The embedded Linux,Uboot etc. , Welcome to study and exchange !
I like running , To play basketball , sleep . Welcome to join me QQ1500836631( remarks CSDN), Learn and communicate with each other , Sharing various learning materials , electronic text , Learning videos, etc .


List of articles


Break the top half 、 The concept of the lower half

Device interrupts interrupt the normal scheduling and operation of kernel processes , The system's pursuit of higher throughput is bound to require the interrupt service program to be as short as possible . however , This good wish often does not coincide with reality . In most real systems , When the interruption comes , The work to be done is often not short , It may have to do a lot of time-consuming processing .
The following figure describes Linux Interrupt handling mechanism of kernel . In order to find a balance between the shortest interrupt execution time and the largest amount of interrupt processing work ,Linux Break the interrupt handler into two halves : Top half and bottom half .
 Insert picture description here

The top half is used to do as little as possible More urgent functions , It tends to be simply Read the interrupt status in the register , And after clearing the interrupt flag “ Interrupt registration ” The job of .“ Interrupt registration ” It means that the bottom half of the processor is hung in the bottom half of the execution queue of the device . such , The top half will be fast , So that more interrupt requests can be served .

Now? , The focus of interrupt processing is on the bottom half , It is needed to complete most of the tasks of interrupt events . Bottom half Almost everything that the interrupt handler does , And it can be New interruptions , This is also the biggest difference between the bottom half and the top half , because The top half is often designed to be uninterrupted . The bottom half is relatively not very urgent , And it's relatively time-consuming , Not executed in hardware interrupt service program .

Although the top half 、 The combination of the bottom half improves the responsiveness of the system , however , Rigidly believe that Linux It is wrong to divide interrupt processing in device driver into two parts . If you interrupt, there is very little work to deal with , It can be done directly in the top half .

In other operating systems, interrupt processing is similar to Linux Methods , Real hardware interrupt service programs are as short as possible . therefore , Many operating systems provide a mechanism combining interrupt context and non interrupt context , Leave the interrupted time-consuming work to be executed in a non interrupted context .

There are three ways to interrupt the lower part

Soft interrupt

Soft interrupt ( Softirq) It's also a traditional bottom half processing mechanism , Its timing is usually When the top half comes back , tasklet It's based on softbreak , So it also runs in soft interrupt context .

stay Linux The kernel , use softing_action Structure represents a soft interrupt , This structure contains the soft interrupt handler pointer and the parameters passed to the function . Use open_softirq() Function can register the corresponding processing function of soft interrupt , and raise_softirq() Function can trigger a soft interrupt .

Soft interrupt and tasklet Run on soft Interrupt context , Still a kind of atomic context , Work queues run on Process context . therefore , In softbreak and tasklet In the processing function Sleep is not allowed , And in the Sleep is allowed in the work queue handler .

local_bh_disable() and llocal_bh_enable() It is used in the kernel to disable and enable soft interrupts and tasklet Function of bottom half mechanism

Copyright notice : This article is an original blog article , follow CC 4.0 BY-SA Copyright agreement , For reprint, please attach the original source link and this statement .
Link to this article :https://blog.csdn.net/qq_16933601/article/details/107239908

Soft interrupt template

asmlinkage void do_softirq(void){__u32 pending;unsigned long flags;/*  Judge whether it is in interrupt processing , If interrupt processing is in progress , Go straight back  */if (in_interrupt())return;/*  Save the value of the current register  */local_irq_save(flags);/*  Get the bitmap of the currently registered softinterrupt  */pending = local_softirq_pending();/*  All soft loops are registered  */if (pending)__do_softirq();/*  Recover the value of the register before interrupt processing  */local_irq_restore(flags);}

tasklet

tasklet It's easy to use , Its execution context is soft interrupt , The timing of execution is usually when the top half returns . We just need to define tasklet And its processing functions , And connecting the two can , for example

void my_tasklet_func(unsigned long); /* Define a processing function */DECLARE_TASKLET(my_tasklet, my_tasklet_func, data);/* Define a tasklet structure my_tasklet, And my_tasklet_func(data) Function */

Code DECLARE_TASKLET(my_tasklet,my_tasklet_func,data) The implementation defines the name as my_tasklet Of tasklet, And with my_tasklet_func() This function is bound to , And the argument to this function is data.
In need of scheduling tasklet I'll quote a tasklet_schedule() Function can make the system schedule at the right time :

tasklet_schedule(&my_tasklet);

Use tasklet As the bottom half, the device driver template that handles interrupts is shown below ( Only interrupt related components are included
branch ).

tasklet Function template

/*  Definition tasklet And the bottom half functions and associate them  */void xxx_do_tasklet(unsigned long);DECLARE_TASKLET(xxx_tasklet, xxx_do_tasklet, 0);/*  Interrupt processing bottom half  */void xxx_do_tasklet(unsigned long).../*  Interrupt processing top half  */
 irqreturn_t xxx_interrupt(int irq, void *dev_id){
 ...
 tasklet_schedule(&xxx_tasklet);
 ...}/*  Device driver module loading function  */
 int __init xxx_init(void){
 ...
 /*  Application interruption  */
 result = request_irq(xxx_irq, xxx_interrupt,
 0, "xxx", NULL);
 ...
 return IRQ_HANDLED;}/*  Device driver module unload function  */
 void __exit xxx_exit(void){
 ...
 /*  Release interrupt  */
 free_irq(xxx_irq, xxx_interrupt);
 ...}

The above program applies for interrupt in the module loading function ( The first 24~25 That's ok ), And unload the function in the module free_irq(xxx_irq, xxx_interrupt); Release it in the air . Corresponding to xxx_irq The interrupt handler for is set to xxx_interrupt() function , In this function ,tasklet_schedule(&xxx_tasklet) Scheduling is defined by tasklet function xxx_do_tasklet() At the right time .

Work queue

How to use work queue and tasklet Very similar , But the execution context of the work queue is the kernel thread , So you can schedule and sleep . The following code defines a work queue and a bottom half execution function

struct work_struct my_wq; /*  Define a work queue  */void my_wq_func(struct work_struct *work); /*  Define a processing function  */

adopt INIT_WORK() You can initialize the work queue and bind it to a handler :

INIT_WORK(&my_wq, my_wq_func);/*  Initialize the work queue and bind it to the handler  */

And tasklet_schedule() The corresponding function for scheduling work queue execution is schedule_work(), Such as :

schedule_work(&my_wq); /*  Scheduling work queue execution  */

Work queue function template

/*  Define work queues and correlation functions  */struct work_struct xxx_wq;void xxx_do_work(struct work_struct *work);/*  Interrupt processing bottom half  */void xxx_do_work(struct work_struct *work).../* Interrupt processing top half */
 irqreturn_t xxx_interrupt(int irq, void *dev_id){
 ...
 schedule_work(&xxx_wq);
 ...
 return IRQ_HANDLED;}/*  Device driver module loading function  */
 int xxx_init(void){
 ...
 /*  Application interruption  */
 result = request_irq(xxx_irq, xxx_interrupt,
 0, "xxx", NULL);
 ...
 /*  Initialize work queue  */
 INIT_WORK(&xxx_wq, xxx_do_work);
 ...}/*  Device driver module unload function  */
 void xxx_exit(void){
 ...
 /*  Release interrupt  */
 free_irq(xxx_irq, xxx_interrupt);
 ...}

The early implementation of work queues was in every CPU Create one on the core worker Kernel thread , All the work on this core is worker Execute in thread , Its concurrency is obviously unsatisfactory . stay Linux 2.6.36 in the future , Turn to “Concurrency-managedworkqueues”, abbreviation cmwq,cmwq The thread pool of the work queue is automatically maintained to improve concurrency , At the same time keep API Backward compatibility of .

Interrupt and context

On process context 、 Some concepts of interrupt context and atomic context

The difference between soft interrupt and hard interrupt

Hard interrupt :

1. Hard interrupt is caused by Hardware generation Of , such as , Like disk , network card , keyboard , Clock, etc . Each device or device set has its own IRQ( Interrupt request ). be based on IRQ,CPU The corresponding request can be distributed to the corresponding hardware driver ( notes : A hardware driver is usually a subroutine in the kernel , Not an independent process ).

2. Drivers that handle interrupts need to run on CPU Upper , therefore , When an interrupt occurs ,CPU Will interrupt the currently running task , To handle interrupts . On systems with multiple cores , Usually, only one interrupt is allowed CPU( There is also a special situation , There is a hardware channel on the mainframe , It can be without a master CPU With the support of , Multiple interrupts can be handled at the same time .).

3. Hard interrupts can be interrupted directly CPU. It causes the relevant code in the kernel to be triggered . For processes that take some time to process , The interrupt code itself can also be interrupted by other hard interrupts .

4. For clock interrupt , The kernel scheduling code will suspend the currently running process , So that other processes can run . It exists to make the scheduling code ( Or scheduler ) You can schedule multiple tasks .

Soft interrupt :

1. Soft interrupt processing is very much like hard interrupt . However , They're just made up of The currently running process Produced by .

2. Usually , Soft interrupts are some of the key to I/O Request . These requests call the kernel that can schedule I/O The procedure that happened . For some devices ,I/O The request needs to be processed immediately , And disk I/O Requests can usually be queued and processed later . according to I/O Different models , The process may be suspended until I/O complete , At this point, the kernel scheduler will select another process to run .I/O Processes can be generated and scheduled between processes, usually with disks I/O In the same way .

3. Softinterrupts are only associated with the kernel . The kernel is mainly responsible for scheduling any other processes that need to run . Some kernels allow parts of the device driver to exist in user space , And the kernel will also schedule this process to run when needed .

4. Soft interrupts don't interrupt directly CPU. also Only the code that is currently running ( Or the process ) Soft interrupt will be generated . This kind of interrupt requires the kernel to do something for the running process ( Usually it is I/O) Request . One special soft interrupt is Yield call , Its function is to request the kernel scheduler to see if there are any other processes that can run .

Hard interrupt 、 The difference between soft interrupt and signal

Hard interrupt is The external device is right CPU The interrupt , Softbreak is A processing mechanism for interrupting the bottom half , And the signal is from kernel ( Or other processes ) The interruption of a process . When it comes to system calls , It's also often said that through softbreak ( for example ARM by swi) Into the kernel , In this case, the concept of soft interrupt refers to that it is caused by Interrupts caused by software instructions , And what our place says softirq It's two completely different concepts , One is software, One is soft.
One thing to note is that , And soft interrupt based on tasklet If it appears in large numbers in a certain period of time , The kernel will put subsequent soft interrupts into ksoftirqd Kernel thread . in general , Interrupt priority is higher than soft interrupt , Soft interrupt is higher than any thread . Soft interrupt is moderately threaded , It can alleviate the response of the system under high load .