First, what is the interruption
The Chinese explanation of interruption is the disconnection, pause or malfunction of the half middle. So why do we need to "block, pause and disconnect" in a computer system?
To give an example of everyday life, for example, I am cooking a pot of water with gas in the kitchen, so I can only stay in the kitchen, waiting for the water to open-if the water spill out of the gas, it is possible that a disaster will occur. Wait, wait, the outside suddenly came a surprise cry "why not turn off the faucet?" "So I am ashamed to find, just after the water to complain about this boring job, incredibly forget it, so panic rushed to the water pipe, nimbly off the faucet, voice and to the ear," How to do is so sloppy? ”。 Stretched out his tongue, this little thing passed, and my lonely eyes fell on the kettle.
Outside the door suddenly came a sonorous song, my favorite costume play to start, really want to door, however, listen to the kettle issued "bubbling" voice, I know: Unless until the water open, otherwise I enjoy life.
What does this scene have to do with interruptions?
If I concentrate on waiting for the water to open is a process, then the call, the music on the television not all let the process "half the middle of the barrier, pause or break down"? Isn't that a living "interruption"?
In this scenario, I am the only one with the ability to deal with, whether it is boiling water, turning off the tap or watching TV, at the same time I can only do a thing. However, when I am focused on one thing, there are always many or urgent or not urgent things suddenly appear in front, need to pay attention to, some still need me to stop the work at hand to deal with immediately. Only after the processing has finished, the party can go back to complete the previous task, "boil a pot of water thoroughly!" ”
The interrupt mechanism not only gives me the ability to deal with unexpected situations, but if I can make full use of this mechanism, I can accomplish multiple tasks "at the same time". Back to the example of boiling water, in fact, whether I am not in the kitchen, the gas stove will always boil, I would like to do, but just in time to turn off the gas stove, in order to be able to complete the action in a second, but let me wait in the kitchen, in 10 minutes of time to constantly see the spout is not the steam, It's not worth it. I decided to watch TV on my mind. Of course, in my lifetime, I did not want to make the kitchen a fire, so I went to the alarm clock, 10 minutes later it will send a "scream", reminding me that the stove on the water boil, then I go to turn off the gas is completely in time. I used an interrupt signal--the alarm--for 10 minutes of happy hour, I can not help but heartily sigh: interrupt mechanism is really a good thing.
It was because of the interrupt mechanism that I was able to methodically "simultaneously" accomplish multiple tasks, and the interrupt mechanism essentially helped me improve the concurrency "processing" capability. It can also bring the same benefits to the computer system: If the keyboard is pressed to get an interrupt signal, the CPU will not have to wait for the keyboard input, if the hard disk read and write to send an interrupt signal, the CPU can be free to focus on "serving the public"- Whether it's the human finger at the fingertips of the keyboard or the head that reads and writes the media, it's too slow compared to the CPU's processing speed. There is no interrupt mechanism, just like we are in the kitchen, the computer has no parallel processing power.
Similar to people, the CPU also has to face the miscellaneous of the situation-the reality of the accident is ubiquitous-there may be users, such as impatient, pounding the keyboard, it is possible that the operation encountered a 0 divisor; and it is possible that the NIC suddenly received a new packet. These require specific analysis of the CPU, either immediately, or postpone the response or ignore it. In any case, the CPU is required to suspend the "at hand" work, to come up with a countermeasure, only after the response, the party can go back to complete the previous mission, "a pot of water completely boil!" ”
Let us first feel the help of the interrupt mechanism for concurrent processing.
Let's use the program to explore the problem of boiling water, if there is no "break" (note that we are just imitating the interruption of the scene, is actually using the asynchronous event-message-processing mechanism to demonstrate the effect of the interruption.) After all, there is no direct connection between user space and actual interrupts, but the asynchronous event mechanism provided by the operating system for user space can be seen as a product of simulation interrupts, designed as follows:
1 voidStayinkitchen ()2 3 {4 5 BOOLwaterisboiled =false;6 7 while(Waterisboiled! =true )8 9 {Ten BOOLVaporgavenoff =false; One if(Vaporgavenoff) Awaterisboiled =true; - Else -waterisboiled =false; the } - - //Gas stove off - printf ("Close gas oven.\n"); + - //all settled down, finally can watch TV, 10 minutes of precious time Ah, lost time ... + Watching_tv (); A at return; - - } -
As you can see, the entire process, as we described earlier, is executed in order and there is no way to complete the concurrency task.
If you use "break", set a 10-minute "alarm" when you start to boil water, and then let the CPU go to watch TV (a bit of difficulty, the implementation is not within our concern, leave it to the reader to solve it:>). When the alarm clock rings, go to the kitchen and turn off the stove.
#include <sys/types.h>#include<unistd.h>#include<sys/stat.h>#include<signal.h>#include<stdio.h>//the alarm clock will execute this programvoidSig_alarm (intSigno) { //Gas stove offprintf ("Close gas oven.\n");}voidWatching_tv () { while(1) { //Oh, leisurely leisurely }} intMain () {//set a timed interrupt after ignitionprintf ("Start to boil water,SetAlarm "); if(Signal (SIGALRM, sig_alrm) = =Sig_err) {Perror ("Signal (SIGALRM) Error"); return-1; } //and then you can watch TV.printf ("Watching tv!\ n "); WATCHING_TV (); return 0;}
Both of these programs are executed in user space. The second procedure is not much related to the interruption, in fact it only uses the signaling mechanism. However, through the comparison of these two programs, we can clearly see how the processing mechanism of asynchronous events improves concurrency processing power.
Alarm Timer:Alarm is equivalent to a timer in the system, if we call alarm (5), then 5 seconds after the "alarm" (actually by the signal mechanism, we do not want to go into the details here, if you are interested in this, please refer to Richard Stevens Immortal Book "Advanced Programming for UNIX Environments". What happens when the alarm rings? The system executes a function, and as to what function it is, the system allows the program to decide for itself. The programmer writes a function and calls signal to register the function so that, once timed, the system invokes the programmer-supplied function (callback function?). Yes, but it doesn't matter how this is achieved here, we don't introduce new concepts and details. In the above example, we provide the function is Sig_alarm, the work is very simple, print "Off gas cooker" message.
The above two examples are very simple, but it is very good to illustrate the problem, first of all, it proves that the use of asynchronous message processing mechanism can improve the system's concurrent processing capacity. More importantly, it reveals the pattern of this processing mechanism. The user designs the handler as needed, and can bind the program to a specific external event, and the system automatically invokes the handler at the time the external event occurs, completing the relevant work. This mode brings the unified management method to the system, and also brings endless function expansion space.
Computer system Implementation Interrupt mechanism is a very complex work, how to say that people are highly intelligent creatures, and computer as a lump of iron, without the guidance of the program to accomplish nothing. While dealing with an interruption process, it is subject to too many restrictions and things to learn.
First, the form of external signals that a computer can receive is very limited. Interrupts are caused by external input, which can be said to be a stimulus. In the case of boiling water, these inputs are sounds and TV music, and we only use sound as an example. In fact, the real world can input human cpu--brain signal a lot, images, smells like can be accepted by us, the information interface is perfect. But the computer is otherwise, the more the way to accept the external signal, the more complex the design implementation, the higher the cost. Therefore, the personal computer (PC) gives all external stimuli only one input mode-a particular format of electrical signals, and the format of the signal, access method, response method, processing steps are all the protocol (specific content will continue to explain later in this article), this signal is interrupted or interrupted signal, And this set of mechanisms is the interrupt mechanism.
Second, computers don't know how to deal with signals. The human brain can handle the external input, I never have to worry about the alarm clock will be helpless-go into the kitchen off the gas, this is absolutely natural things, but also with the brain think ah, calf belly all know-unfortunately the computer does not, no program, it does not budge. Therefore, there must be a mechanism to ensure that when the external interrupt signal arrives, the correct program is executed at the right time.
Also, the computer does not know how to maintain the continuity of the work. When I was watching TV, if I went to the kitchen to turn off the gas, I could continue to carry on the TV in the end without too much influence. And the computer is not, if put down the work directly to deal with the "accident" interruption, then it can no longer think of what has been done, to what extent. Naturally, there is no chance of "going on". This way of processing is not concurrent execution, but the east of a hammer, west a wooden club.
So how does a general-purpose computer system solve these problems? It is the whole process of implementing interrupt processing by hardware and software coordination. We will introduce this process through the implementation of the Intel X86 architecture.
After the CPU executes one instruction, the logical address of the next instruction is stored in the register of CS and EIP. Before executing a new instruction, the control unit checks to see if there is an interruption or an exception occurred during the execution of the previous instruction. If so, the control unit will drop the instruction and enter the following process:
1. Determine the vector I (0 <= i <= 255) associated with the interrupt or exception
2. Find the corresponding handler for the vector
3. Save current "work site", execute interrupt or exception handler
4. After the execution of the processing procedure, return control to the control unit
5. Control unit recovery site, return to continue the original program
The entire process is as follows:
Figure one: Interrupt handling process
Let's go into this process and see what's going on.
1. What is the concept of anomaly?
The processor generates an exception when the processor executes an error instruction (such as a divisor of 0) due to a programming mistake, or if a special case occurs during execution (for example, a missing fault) that needs to be handled by the operating system. For most processor architectures, handling exceptions and processing interrupts are essentially the same, as are the CPUs of the x86 architecture. There are some differences between exceptions and interrupts, and the generation of exceptions must take into account synchronization with the processor clock. In fact, exceptions are often referred to as synchronous interrupts.
2. What is the interrupt vector?
The interrupt vector represents the interrupt source--in a way that can be thought of as a type of break or exception. There are many types of interrupts and exceptions, such as 0 is an exception, the fault is an exception, the network card will interrupt, the sound card will also produce interrupts, how the CPU distinguish them? The concept of interrupt vectors is derived from this, in fact, it is a sent to the CPU data line of an integer. The CPU assigns a type number to each IRQ to identify different types of interrupts through this integer CPU. There may be a lot of friends here who will ask why the interrupt vector is so troublesome? Why don't you just use irq0~irq15 to finish? For example let IRQ0 for 0,irq1 1 ..., this is not to be simple how? In fact, this embodies the modular design rules, and save the rules.
First of all, we talk about the saving rules, the so-called saving rule is the number of lines used by the less the better, so that if each IRQ is independent use of a data cable, such as IRQ0 with line Line 0, IRQ1 with line Line 1 ... In this way, 16 IRQ will use 16 lines, which is obviously a waste. Then maybe a friend will say: "Then only use 4 lines not just?" (2^4=16).
This problem embodies the rules of module design. We said earlier that there are many classes of interrupts, either external hardware triggers, or software triggers, but interrupts are interrupts for the CPU, and only one that the CPU does not control whether it is triggered by external hardware or by the running software itself, because for the CPU, The process of interrupt processing is the same: interrupt the current program, go to the Interrupt service program to execute, and return to the interrupted program to continue execution. The CPU can handle a total of 256 interrupts, not knowing, and should not let the CPU know whether this is the hardware to interrupt or software to interrupt, so that the CPU can be designed independent of the design of the interrupt controller, so that the CPU needs to complete the work is very simple. The CPU provides only one interface for other modules, which is 256 interrupt processing vectors, also known as interrupt numbers. These interrupt controllers use one of these 256 interrupt numbers to interact with the CPU, for example, the hardware interrupt can use the first 128 numbers, the software interrupts the use of the 128 number, or the software interrupts the use of the first 128, the hardware interrupts the use of 128 numbers, which is completely unrelated to the CPU, When you need to deal with it, just tell the CPU which interrupt number you are using, without telling the CPU where you are from the interrupt. This also facilitates the subsequent expansion, such as now the machine added a piece of 8259 chips, then the chip can use the idle interrupt number, to see which one of the idle use which, instead of having to use the No. 0, or the 1th number of the interrupt number. In fact, this is equivalent to a mapping mechanism, the IRQ signal is mapped to different interrupt numbers, IRQ arrangement or numbering is fixed, but by changing the mapping mechanism, you can let the IRQ map to different interrupt number, can also say that the call different interrupt service program.
3. What is an interrupt service program?
In response to a specific interrupt, the kernel executes a function called an interrupt handler (interrupt handler) or an Interrupt service program (Interrupt Services Routine (ISR)). Each device that generates an interrupt has a corresponding interrupt handler. For example, a function specifically handles interrupts from the system clock, while another function specifically handles interrupts generated by the keyboard.
In general, the Interrupt Service program is responsible for interacting with the hardware, telling the device that the interrupt has been received. In addition, other relevant work needs to be done. For example, the Network Device interrupt service program in addition to the hardware response, but also to the hardware from the network packet copy to memory, processing it before handing over to the appropriate protocol stack or application. Each interrupt service program is different in complexity depending on the task it is trying to accomplish.
In general, a device's Interrupt service program is part of its device driver, device driver, which is the kernel code used to manage the device.
4. Isolate changes
I wonder if you realize how simple and graceful the design of this part of interrupt processing is. People are highly intelligent, able to meet the various unexpected situations to do targeted treatment, the computer compared to the gap is far away, it can only be operated according to the scheduled program. For a computer, hardware support can only interrupt the way the signal is transmitted and how the CPU receives it, and how to deal with the interruption must be implemented by the operating system. The operating system supports all pre-anticipated interrupt signals and theoretically does not pose a major challenge, but when the operating system is installed on a computer device, it is certain that new peripherals will always be added to the system, which can lead to unexpected interruptions when installing the system. How to support this kind of expansion is the whole system must face.
The collaboration of hardware and software here brings us the perfect answer. When new devices introduce new types of interrupts, the CPU and the operating system do not have to focus on how to handle it. The CPU is only responsible for receiving the interrupt signal and referring to the interrupt service program, while the operating system provides the default interrupt service-generally ignoring this signal and returning it-and is responsible for providing the interface to allow the user to register the interrupt service program based on the specific functions of the device. If a user registers a service program that corresponds to an interrupt, the CPU invokes the user-registered service program when the interrupt arrives. In this way, it is completely independent of the CPU architecture and the operating system design in order to interrupt how the temporary system needs to operate the hardware and how to implement the hardware functions.
And when you need to add a new device, only need to tell the operating system that the device occupies the interrupt number, according to the interface format required by the operating system to compose the interrupt service program, using the functions provided by the operating system to register the service program, the interruption of the device is supported by the system.
Interrupts and the processing of interrupts are decoupled. In this way, neither the CPU architecture nor the operating system needs to change when you need to add a new interrupt, when you need to change the service program for an existing outage, or when you cancel support for an interrupt.
5, Save the current work "scene"
After the interruption has been processed, the computer generally has to go back to the work that was being done at hand. This brings some additional "connotation" to the concept of interruption. Note A "Back" does not mean to re-do from scratch, but to continue the progress just now. This requires that the work "live" be retained before the interrupt signal is processed. The word "scene" is more obscure, in fact, refers to a set of information, it can reflect the status of a task at a certain point in time, and can be guaranteed to follow this information to restore the task to that State, continue to carry out. A bit more straightforward, the scene is just a set of register values. How to protect the scene and restore the scene is one of the important considerations for the interrupt mechanism.
Each interrupt processing goes through this save and restore process, and we can abstract out the steps:
1. Save the scene
2. Execution of specific interrupt service procedures
3. Returning from interrupt Service
4. Recovery site
As said above, "scene" seems to be changing, no instant the same. But there is no change in the actual elements that make up the scene. In other words, as long as we save the relevant register state, the scene can be saved. Restoring "Live" is the re-loading of these registers. In other words, for any interruption, the protection site and the recovery site are doing exactly the same operation.
Since the operation is the same, the procedure and code for implementing the operation are the same. Reducing the code redundancy is the basic principle of modular design, there is no reason for all the interrupt service program to repeat the implementation of such a function, it should be as a basic structure by the underlying operating system or hardware to complete. The process of processing the interrupt needs to be done quickly, so the Intel CPU controller assumes this task, and all the steps above are cured and the controller is driven. Both the save site and the recovery site are automatically completed by the hardware, which greatly reduces the burden on the operating system and device drivers.
6. Hardware-to-interrupt support details
The following section, originally should be introduced 8259, interrupt controller programming, interrupt descriptor sheet, and so on, but I saw the "protection mode of 8259A chip programming and Interrupt processing research" (see Resources 1), the previous statement prepared, the reader directly read it well.
From the outside, Linux support for interrupts
In Linux, the interrupt handler looks like an ordinary C function. Only these functions must be declared according to a particular type, so that the kernel can pass the handler's information in a standard way, and in other respects, it looks indistinguishable to the normal function. The real difference between interrupt handlers and other kernel functions is that interrupt handlers are called by the kernel to respond to interrupts, and they run in a special context that we call the interrupt context. For the interrupt context, we'll discuss it later.
Interrupts can occur at any time, so an interrupt handler can be executed at any time. Therefore, it is important to ensure that the interrupt handler executes quickly so that the execution of the interrupted code can be resumed as soon as possible. Therefore, while it is important for hardware to quickly service its outages. For other parts of the system, however, it is equally important to have the interrupt handler complete execution in as short a time as possible.
Even the most streamlined version of the interrupt Service program, which also interacts with the hardware, tells the device that the interrupt has been received. But usually we can't offload the interrupt service program like this, instead, we rely on it to do a lot of other work. As an example, we can consider the challenges faced by interrupt handlers for network devices. In addition to answering the hardware, the handler copies the network packets from the hardware to memory, processes them, and then gives them to the appropriate protocol stack or application. Obviously, this amount of exercise is not too small.
Now let's analyze what the Linux operating system needs to do to support the interrupt mechanism.
First, the operating system must ensure that new interrupts are supported. The computer system hardware left the peripherals with a unified interrupt signal interface. It cures the interrupt signal access and delivery method, take the PC, the interrupt mechanism by two 8259 and the CPU to achieve collaboration. The peripheral has to do is to send the interrupt signal to a specific pin of 8259, so that 8259 will allocate an identity for this interrupt-that is, the interrupt vector, the interrupt vector, the CPU can be in the interrupt vector index of the table-interrupt vector table-to find the Interrupt service program, It determines how the interrupt is handled specifically. (For details, please refer to reference 1, which is a wonderful description of why this mechanism is used). This is a hardware-defined mechanism that the software can only obey unconditionally.
Therefore, the operating system support for new interrupts, said simply, is to maintain the interrupt vector table. The new peripheral device joins the system, first must be clear about its interrupt vector number, but also to provide its own interrupt service program, and then use the Linux kernel call interface, the interrupt vector number, interrupt service program This information into the interrupt vector table. This allows the CPU to automatically invoke the interrupt service program when it receives the interrupt signal. This registration operation is typically done by the device driver.
Second, the operating system must provide programmers with a simple and reliable programming interface to support interrupts. The basic flow of interrupts is already mentioned, and it interrupts the work that is currently in progress to execute the Interrupt service program before returning to the previous task. There are a number of problems to be solved: how to protect the scene, how to handle nested interrupts, and so on, the operating system should be resolved. Programmers, even developers of drivers, seldom need to be pitied by interrupted processes when writing interrupt service programs. (Of course, for the sake of improving system efficiency, writing a driver is a lot more than writing a user-level program, who let us top the system Programmer's Halo?) )
The operating system shields us from the details of dealing with interrupt-related hardware mechanisms, provides a streamlined interface, and allows us to implement support for actual interrupts in a very simple way, how does Linux do it perfectly?
CPU-to-interrupt process:
We must first understand what the CPU will do when it receives the interrupt signal. No way, the operating system must understand the mechanism of hardware, do not cooperate with the hardware will be unable to. Now we assume that the kernel has been initialized and that the CPU is running in protected mode.
After the CPU executes one instruction, the logical address of the next instruction is stored in the register of CS and EIP. Before executing a new instruction, the control unit checks to see if there is an interruption or an exception occurred during the execution of the previous instruction. If so, the control unit will drop the instruction and enter the following process:
1. Determine the vector I (0£i£255) associated with the interrupt or exception.
2. The IDTR register reads item I from the IDT table (in the following description, we assume that the IDT table entry contains an interrupt gate or a trap gate).
3. Obtain the base address of the GDT from the GDTR register and look in the GDT table to read the segment descriptor identified by the selector in the IDT table entry. This descriptor specifies the base address of the segment where the interrupt or exception handler is located.
4. Make sure that the interruption is from the source of the authorized (interrupted) occurrence. Compare the current privileged CPL (lower two bits of the CS register) with the descriptor privilege level of the segment descriptor (that is, DPL, which is stored in the GDT), and if the CPL is smaller than DPL, a "generic protection" exception occurs because the interrupt handler's privileges cannot be lower than the privileges of the program that caused the interruption. For programming exceptions, further security checks are performed: Compare the CPL with the gate descriptor in IDT, and if DPL is smaller than CPL, a "generic protection" exception is generated. This last check prevents the user application from accessing special trap doors or breaking gates.
5. Check if a change in the privilege level has occurred, that is, whether the CPL differs from the selected segment descriptor's DPL. If so, the control unit must start using the stack associated with the new privilege level. Do this by performing the following steps:
A. Read the TR register to access the TSS segment of the running process.
B. Load the SS and ESP registers with the correct values for the stack segments and stack pointers associated with the new privilege level. These values can be found in the TSS (see chapter III, "Task Status section").
C. Save the previous values of SS and ESP in the new stack, which define the logical address of the stack associated with the old privilege level.
6. If the fault has occurred, load CS and EIP registers with the instruction address that caused the exception, so that the instruction can be executed again.
7. Save the contents of Eflag, CS and EIP in the stack.
8. If the exception produces a hard error code, save it in the stack.
9. Load CS and EIP registers whose values are segment selectors and offset fields for the I-entry descriptor in the IDT table, respectively. These values give the logical address of the first instruction of the interrupt or exception handler.
The last step performed by the control unit is to jump to an interrupt or exception handler. In other words, when the interrupt signal is processed, the command executed by the control unit is the first instruction of the selected handler.
After the interrupt or exception is processed, the corresponding handler must produce a iret instruction that transfers control to the interrupted process, which forces the control unit:
1. Load CS, EIP, or eflag registers with values stored in the stack. If a hard error code has been pressed into the stack, and above the EIP content, then the hard error code must be ejected before executing the iret instruction.
2. Check that the CPL of the handler is equal to the lowest two-bit value in CS (this means that the interrupted process is running at the same privilege level as the handler). If yes, iret terminates execution; otherwise, proceed to the next step.
3. Load SS and ESP registers from the stack, so return to the stack associated with the old privilege level.
4. Check the contents of DS, ES, FS, and GS segment registers, if one of the registers contains the selector is a segment descriptor, and its DPL value is less than CPL, then clear the corresponding segment register. The control unit does this to prohibit the user-state program (CPL=3) from using the previously used segment Register (dpl=0) of the kernel. If these registers are not clear, a malicious user program may use them to access the kernel address space.
Again, the operating system must ensure that interrupt information is delivered efficiently and reliably
Note: So Poweroff (shutdown) is not an interruption? If it is literally, it certainly conforms to the Chinese definition of interruption, but from the signal format, processing methods and so on, it is difficult to meet our understanding. What does Intel say? This interrupt does not employ a common interrupt handling mechanism. So is it an interruption in the end? I can not say: (
Note Two: More detailed content and some other considerations please refer to the kernel source code package Documentations/rtc.txt
Note Three: These functions are implemented using assembly instead of C, because the C compiler pushes additional stack information into the implementation of the function. And the CPU in the interrupt to temporarily save and restore the scene are in strict format, a byte change can not have.
Resources
1 "8259A chip programming and interrupt processing in protected mode" Xiao Han hit pure C forum http://purec.binghua.com/Article/ShowArticle.asp?ArticleID=91
2 "80x86 IBM PCand compatible computers (volumeIand volumesII):assembly language, design and interface technology" Muhammad Ali MazidiWait for Zhang Bosuch as translation Tsinghua University Press
3 "The implementation of keyboard interaction of writing operating system " Xiao han hit pure C Forum http://purec.binghua.com/Article/ShowArticle.asp?ArticleID=104
Interrupt parsing [Go]