Reference: http://blog.csdn.net/tiangwan2011/article/details/7254752
Starting from linux1.x, the interrupt handler is conceptually divided into the top half (top half) and the bottom half (bottom half ). When an interruption occurs, the upper half of the processing process is immediately executed, because it completely blocks the interruption, so it should be fast, Otherwise other interruptions will not be processed in a timely manner. However, the lower half (if any) does almost everything to interrupt the processing program.
Deferred execution. The kernel processes the upper half and lower half as independent functions. The upper half functions as "registration interruption" and determines whether the lower half of the kernel needs to be executed. The part that needs to be executed immediately must be in the upper half, and the part that can be postponed may belong to the lower half. The task in the lower half is to execute the work closely related to the interrupt processing but not in the upper half. For example, to view the device to obtain the information about the interruption, and perform corresponding processing based on the information (generally obtained by reading the registers on the device. From this we can see that the lower half is actually caused by the upper half. For example, when a medium disconnection occurs on the printer port, the disconnection handler will immediately execute the relevant upper half, the upper part produces a Soft Interrupt (one of the lower half) and sends it to the kernel of the operating system, so that the kernel will wake up and sleep Based on the Soft Interrupt.
Processes in the sleeping printer task queue.
Break down
Why is an interruption divided into two parts? The following typical causes can be well explained.
1. interruption can interrupt the execution of other programs at any time. If the interrupted code is very important to the system, the shorter the execution time of the interrupt processing program, the better.
2. as we know from the above, when the Interrupt Processing Program is being executed, it will block the interrupt requests of the same interrupt line. What's more serious is that if irqf_disabled is set, the interrupt service program will block all other interrupt requests. The faster the interrupt handler is executed, the better.
In the above examples, the shorter the execution time of the interrupted service program, the better. Generally, the interrupt handler is executed in the upper half. In fact, in almost all cases, the upper half only executes the interrupt processing program. Therefore, we can think that a complete interrupt processing process is completed by the Interrupt Processing Program and the lower half.
There is a reason for this division, because we must have a fast, asynchronous, and simple handler dedicated to responding quickly to hardware interrupt requests, at the same time, it is necessary to complete those operations that have strict time requirements. While those with relatively loose time requirements, other remaining work will be executed at any time later, that is, in the so-called lower half.
In short, the division of an interrupt processing process is mainly to reduce the workload of the interrupt processing program (of course, it is ideal to leave all the work to the lower half. However, the interrupt handler should at least complete the response to the interrupt request .), Because at least the same level of Interrupt requests will be blocked during its operation, these are directly related to the response capability and performance of the entire system. During the execution of the second half, all interruptions are allowed to be responded. Unlike the upper half, the interrupt handler can only be used. The lower half can be implemented through multiple mechanisms: tasklet, work queue, and Soft Interrupt.
The biggest difference between the upper part and lower part is that the upper part cannot be interrupted, while the lower part can be interrupted. Ideally, it is best to deliver all the work to the lower half of the interrupt processing program for execution in the upper half of the interrupt processing program. In this way, little work is done in the upper half of the interrupt processing program, and return as quickly as possible. However, the upper half of the interrupt handler must complete some work, such as confirming the arrival of the interrupt through operating the hardware, and some time-sensitive work such as copying data from the hardware. The rest of the work can be performed in the lower half.
There are no strict rules for the division between the upper half and the lower half, which depends on the programming habits of driver developers, but there are still some habits for reference:
I. If the task is time-sensitive, put it in the upper half for execution.
Ii. if the task is related to hardware, it is generally executed in the upper half.
Iii. if the task is to be executed in the upper half of the task to ensure that it is not interrupted by other interruptions, It will be executed (because this is a system disconnection ).
Iv. Perform other less urgent tasks in the lower half.
In the lower half, you don't need to specify the exact time. You just need to postpone these tasks a little so that they can be executed after the system is not busy and the recovery is interrupted. Generally, the lower half of the interrupt handler will run immediately when it returns a result. The key to executing the lower half is to allow all the interruptions to be responded when they are running. The lower half is a type of push-back task, which delays some less urgent tasks to a more convenient time for the system to run. The method for implementing the lower half of the kernel is constantly evolving. At present, we have derived BH (removed in 2.5) and Soft Interrupt (softirq introduced in 2.3) from the original BH (bottom half) tasklet (introduced in 2.3) and work queue (introduced in 2.5 ). The last three methods are analyzed and discussed here.