Linux takes advantage of exceptions to achieve two quite different goals:
To send a signal to a process to notify an anomalous condition
To handle demand paging
An example of the first use is if a process performs a division by 0. The CPU raises a "Divide error" exception, and the corresponding exception handler sends a SIGFPE signal to the current process, which will then take the necessary steps to recover or (if no signal handler is set for that signal) abort.
Exception handlers have a standard structure consisting of three parts:
Save the contents of most registers in the Kernel Mode stack (this part is coded in Assembly language).
Handle the exception by means of a high-level C function.
Exit from the handler by means of the ret_from_exception( ) function.
In order to take advantage of exceptions, the IDT must be properly initialized with an exception handler function for each recognized exception. It is the job of the trap_init( )function to insert the final values—that is, the functions that handle the exceptions—into all IDT entries that refer to nonmaskable interrupts and exceptions. This is accomplished through the set_trap_gate and set_system_gate macros:
set_trap_gate(0,÷_error); set_trap_gate(1,&debug); set_trap_gate(2,&nmi); set_system_gate(3,&int3); set_system_gate(4,&overflow); set_system_gate(5,&bounds); set_trap_gate(6,&invalid_op); set_trap_gate(7,&device_not_available); set_trap_gate(8,&double_fault); set_trap_gate(9,&coprocessor_segment_overrun); ...