previous | start | next

System Calls

A simple model of system call implementation on the IA32 architecture:

The operating system has a table consisting of exception handlers (and interrupt handlers)

Each entry consists of a
(1) handler function address and
(2) a set of flags (as an int)

Each system call has a corresponding system call number. For example suppose getpid() has system call number 32.

The library routine for getpid() that is linked into a user program has code like this:

 move $32,%eax   ; assume 32 is the number for getpid() - no parameters
 int  $0x80      ; invoke trap instruction

The trap instruction saves the call user's context (registers including the flags register, %esp, %eip...) AND loads the %eip and flags register from the entry in the exception table corresponding to 0x80 AND switches to the kernel stack for this user.

Note that the processor will be in kernel mode because of the new flags register value and will be executing kernel code because of the %eip register value.

The handler for entry 0x80 starts executing in kernel mode.

This handler is for system calls. It just checks %eax and then indexes into another table (using the value 32 in %eax) to determine what kernel function is being called - do_getpid() in this case and calls this function indirectly using the table entry.

The kernel is then executing do_getpid() in the context of the current thread (and process). A global pointer references the currently executing current thread. So it can look up the information (pid in this case) and arrange to return that value.

Returning is a bit different than returning from an oridnary call as the registers need to be reloaded with the user's saved registers to restore the user to the user stack and frame. But also the user's flag register value must be reloaded to return to user mode.



previous | start | next