Chapter 8-01

来源:互联网 发布:拉沙德刘易斯生涯数据 编辑:程序博客网 时间:2024/06/06 10:22

Please indicate the source: http://blog.csdn.net/gaoxiangnumber1.
From the time you first apply power to a processor until the time you shut it off, the program counter assumes a sequence of values
a0 , a1, … , an−1
where each ak is the address of some corresponding instruction Ik . Each transition from ak to ak+1 is called a control transfer. A sequence of such control transfers is called the flow of control, or control flow of the processor.
The simplest kind of control flow is a “smooth” sequence where each Ik and Ik+1 are adjacent in memory. Abrupt changes to this smooth flow, where Ik+1 is not adjacent to Ik , are caused by familiar program instructions such as jumps, calls, and returns. Such instructions are necessary mechanisms that allow programs to react to changes in internal program state represented by program variables.
Systems must be able to react to changes in system state that are not captured by internal program variables and are not related to the execution of the program. For example, a hardware timer goes off at regular intervals and must be dealt with.
Modern systems react to these situations by making abrupt changes in the control flow. We refer to these abrupt changes as exceptional control flow (ECF).
Exceptional control flow occurs at all levels of a computer system. For example, at the hardware level, events detected by the hardware trigger abrupt control transfers to exception handlers. At the operating systems level, the kernel transfers control from one user process to another via context switches. At the application level, a process can send a signal to another process that abruptly transfers control to a signal handler in the recipient. An individual program can react to errors by sidestepping the usual stack discipline and making nonlocal jumps to arbitrary locations in other functions.
8.1 Exceptions
Exceptions are a form of exceptional control flow that are implemented partly by the hardware and partly by the operating system.
An exception is an abrupt change in the control flow in response to some change in the processor’s state.

In the figure, the processor is executing some current instruction Icurr when a significant change in the processor’s state occurs. The state is encoded in various bits and signals inside the processor. The change in state is known as an event. The event might be directly related to the execution of the current instruction. For example, a virtual memory page fault occurs. On the other hand, the event might be unrelated to the execution of the current instruction. For example, a system timer goes off or an I/O request completes.
In any case, when the processor detects that the event has occurred, it makes an indirect procedure call (the exception), through a jump table called an exception table, to an operating system subroutine (the exception handler) that is specifically designed to process this particular kind of event.
When the exception handler finishes processing, one of three things happens, depending on the type of event that caused the exception:
The handler returns control to the current instruction Icurr , the instruction that was executing when the event occurred.
The handler returns control to Inext , the instruction that would have executed next had the exception not occurred.
The handler aborts the interrupted program.
8.1.1 Exception Handling
Each type of possible exception in a system is assigned a unique nonnegative integer exception number. Some of these numbers are assigned by the designers of the processor. Other numbers are assigned by the designers of the operating system kernel. Examples of the former include divide by zero, page faults, memory access violations, breakpoints, and arithmetic overflows. Examples of the latter include system calls and signals from external I/O devices.
At system boot time (when the computer is reset or powered on), the operating system allocates and initializes a jump table called an exception table, so that entry k contains the address of the handler for exception k.

At run time (when the system is executing some program), the processor detects that an event has occurred and determines the corresponding exception number k. The processor then triggers the exception by making an indirect procedure call, through entry k of the exception table, to the corresponding handler.

Figure 8.3 shows how the processor uses the exception table to form the address of the appropriate exception handler. The exception number is an index into the exception table, whose starting address is contained in a special CPU register called the exception table base register.
An exception’s differences to a procedure call:
As with a procedure call, the processor pushes a return address on the stack before branching to the handler. However, depending on the class of exception, the return address is either the current instruction (the instruction that was executing when the event occurred) or the next instruction (the instruction that would have executed after the current instruction had the event not occurred).
The processor also pushes some additional processor state onto the stack that will be necessary to restart the interrupted program when the handler returns. For example, an IA32 system pushes the EFLAGS register containing, among other things, the current condition codes, onto the stack.
If control is being transferred from a user program to the kernel, all of these items are pushed onto the kernel’s stack rather than onto the user’s stack.
Exception handlers run in kernel mode, which means they have complete access to all system resources.
Once the hardware triggers the exception, the rest of the work is done in software by the exception handler. After the handler has processed the event, it optionally returns to the interrupted program by executing a special “return from interrupt” instruction, which pops the appropriate state back into the processor’s control and data registers, restores the state to user mode if the exception interrupted a user program, and then returns control to the interrupted program.
8.1.2 Classes of Exceptions
Exceptions can be divided into four classes: interrupts, traps, faults, and aborts.

Interrupts
Interrupts occur asynchronously as a result of signals from I/O devices that are external to the processor. Hardware interrupts are asynchronous in the sense that they are not caused by the execution of any particular instruction. Exception handlers for hardware interrupts are often called interrupt handlers.

I/O devices such as network adapters trigger interrupts by signaling a pin on the processor chip and placing onto the system bus the exception number that identifies the device that caused the interrupt.
After the current instruction finishes executing, the processor notices that the interrupt pin has gone high, reads the exception number from the system bus, and then calls the appropriate interrupt handler. When the handler returns, it returns control to the next instruction (i.e., the instruction that would have followed the current instruction in the control flow had the interrupt not occurred). The effect is that the program continues executing as though the interrupt had never happened.
The remaining classes of exceptions (traps, faults, and aborts) occur synchronously as a result of executing the current instruction. We refer to this instruction as the faulting instruction.
Traps and System Calls
Traps are intentional(故意的) exceptions that occur as a result of executing an instruction. Trap handlers return control to the next instruction. The most important use of traps is to provide an interface between user programs and the kernel known as a system call.
User programs often need to request services from the kernel such as creating a new process (fork). To allow controlled access to such kernel services, processors provide a special “syscall n” instruction that user programs can execute when they want to request service n. Executing the syscall instruction causes a trap to an exception handler that decodes the argument and calls the appropriate kernel routine.

From a programmer’s perspective, a system call is identical to a regular function call. However, their implementations are quite different. Regular functions run in user mode, which restricts the types of instructions they can execute, and they access the same stack as the calling function. A system call runs in kernel mode, which allows it to execute instructions, and accesses a stack defined in the kernel.
Faults
Faults result from error conditions that a handler might be able to correct. When a fault occurs, the processor transfers control to the fault handler. If the handler is able to correct the error condition, it returns control to the faulting instruction, thereby reexecuting it. Otherwise, the handler returns to an abort routine in the kernel that terminates the application program that caused the fault.

A classic example of a fault is the page fault exception, which occurs when an instruction references a virtual address whose corresponding physical page is not resident in memory and must therefore be retrieved from disk. A page is a contiguous block (typically 4 KB) of virtual memory. The page fault handler loads the appropriate page from disk and then returns control to the instruction that caused the fault. When the instruction executes again, the appropriate physical page is resident in memory and the instruction is able to run to completion without faulting.
Aborts
Aborts result from unrecoverable fatal errors, typically hardware errors such as parity errors that occur when DRAM or SRAM bits are corrupted. Abort handlers never return control to the application program. As shown in Figure 8.8, the handler returns control to an abort routine that terminates the application program.

8.1.3 Exceptions in Linux/IA32 Systems
There are up to 256 different exception types defined for IA32 systems. Numbers in the range from 0 to 31 correspond to exceptions that are defined by the Intel architects, and thus are identical for any IA32 system. Numbers in the range from 32 to 255 correspond to interrupts and traps that are defined by the operating system.

Linux/IA32 Faults and Aborts
Divide error.
A divide error (exception 0) occurs when an application attempts to divide by zero, or when the result of a divide instruction is too big for the destination operand. Unix does not attempt to recover from divide errors, choose instead to abort the program. Linux shells typically report divide errors as “Floating exceptions.”
General protection fault.
The general protection fault (exception 13) occurs for many reasons, usually because a program references an undefined area of virtual memory, or because the program attempts to write to a read-only text segment. Linux does not attempt to recover from this fault. Linux shells typically report general protection faults as “Segmentation faults.”
Page fault.
A page fault (exception 14) is an example of an exception where the faulting instruction is restarted. The handler maps the appropriate page of physical memory on disk into a page of virtual memory, and then restarts the faulting instruction.
Machine check.
A machine check (exception 18) occurs as a result of a fatal hardware error that is detected during the execution of the faulting instruction. Machine check handlers never return control to the application program.
Linux/IA32 System Calls
Linux provides hundreds of system calls that application programs use when they want to request services from the kernel. Each system call has a unique integer number that corresponds to an offset in a jump table in the kernel.

System calls are provided on IA32 systems via a trapping instruction called int n, where n can be the index of any of the 256 entries in the IA32 exception table. Historically, system calls are provided through exception 128 (0x80).
C programs can invoke any system call directly by using the syscall function. The standard C library provides a set of convenient wrapper functions for most system calls. The wrapper functions package up the arguments, trap to the kernel with the appropriate system call number, and then pass the return status of the system call back to the calling program.
We will refer to system calls and their associated wrapper functions interchangeably as system-level functions.
How programs can use the int instruction to invoke Linux system calls directly? All parameters to Linux system calls are passed through general purpose registers rather than the stack. Register %eax contains the syscall number, and registers %ebx, %ecx, %edx, %esi, %edi, and %ebp contain up to six arbitrary arguments. The stack pointer %esp cannot be used because it is overwritten by the kernel when it enters kernel mode.
Consider the following program, written using the write system-level function:

The first argument to write sends the output to stdout. The second argument is the sequence of bytes to write, and the third argument gives the number of bytes to write.

Figure 8.11 shows an assembly language version of hello that uses the int instruction to invoke the write and exit system calls directly. Lines 9–13 invoke the write function. First, line 9 stores the number for the write system call in %eax, and lines 10–12 set up the argument list. Then line 13 uses the int instruction to invoke the system call. Similarly, lines 14–16 invoke the exit system call.
Please indicate the source: http://blog.csdn.net/gaoxiangnumber1.

0 0
原创粉丝点击