Kernel Mode, User Mode, and System Calls

Kernel Mode vs. User Mode –

The CPU executes instructions on behalf of the kernel, other system programs and user programs.

  • When executing instructions on behalf of the kernel, the system is in kernel mode (kernel space)
  • When executing instructions on behalf of other system programs and user program, it is in user mode (user space)

There is a mode bit in the hardware to distinguish which mode the computer is running in.  When the system is in kernel mode the system is executing trusted code. This trusted code has full access to all of the resources on the computer.  When in user mode, processes must make system calls to request access to system resources.

System Calls

When a user space program needs access to system resources it may request access by calling system functions or by calling library functions which in turn make system calls.  

System calls are calls to trusted kernel code that provide access to system resources.  Many UNIX based systems (e.g. MacOS, Linux) provide a set of system calls that are POSIX (Portable Operating System Interface) compliant.

When a system call is made, the following process occurs:

  • The call is made through a wrapper macro that was compiled into the program binary
  • The wrapper assembly code pushes the parameters onto a parameter stack and requests the CPU switch from user mode (if in user mode) to kernel mode and start executing a specific routine using an interrupt instruction.
  • The kernel then takes over and identifies which system call was called and executes the correct system-call handler using the data on the stack.
  • After the system call is executed, a value is usually returned (and sets errno if the return code is negative) and the CPU may switch to user mode.

Resource: http://www.tldp.org/LDP/khg/HyperNews/get/syscall/syscall86.html

There are dozens of system calls available for application programmers.  A quick reference can be found here.  POSIX compliant operating systems also include manual pages that provide information on system functions and C standard library functions.  The manual pages can be accessed via the web or in a terminal.  To view a manual page in a terminal, simply type man followed by the name of the function on the command line.

Making System Calls in C

Every system call has its declaration defined in a header file.  To determine the name of the header file, refer to the system call’s man page.  When you’ve identified the name of the header file, reference the header file in your source code with an include statement as shown below.

#include <header_file_name.h>

As mentioned above, most system calls return a negative number upon error and set a global variable named errno to an integral value which can be used to identify the error that occurred when the system call was being executed.  You can determine what values are returned by a system call by reading the system call’s man page.  When calling a system function, it is important to check the return value of the system call.  Often, an application program can not proceed if a system call does not complete properly.  The C standard library function strerror() can be used to print a human readable error message based on the value in the global variable errno.  The header file for strerror is <string.h>.

For example, kill() is a system call that sends a signal to a running process based on the process’ process identifier (pid).  Upon error, kill() returns -1.  To properly call kill we should check the value returned by kill() and if it is -1, we should log the error and then act accordingly.

pid_t pid;
int signo;
...

if (kill(pid, signo) == -1) {
    printf("Error calling kill: %s\n", strerror(errno));
    ...
}

© 2017 – 2018, Eric. All rights reserved.