What is a System Call
Every program will require some operating systems service, if for nothing else to do I/O.
A user process has its own virtual address space, and when it is not making use of OS services, it is said to be executing in user space. It cannot directly address operating system memory (or another process's memory), so you cannot make an ordinary function call into the kernel. There are only two ways to get the Unix operating system to do something for a process: it must either raise an exception or perform a system call. When one of these things happens, the process enters kernel space. At this point, the kernel is said to be executing on behalf of the process. A context switch occurs whenever the actual processor changes virtual address spaces, and context switches are much more expensive then a function call.
A deliberate invocation of the kernel is called a
system call, and the exact mechanism is
processor/architecture dependent. Most processors hava
trap
or syscall
machine instruction.
Intel processors have an int
(interrupt) machine
instruction, for example.
In C, system calls are handled through the normal function call
mechanism; that is, you call a C function (or use a macro) that
will produce the assembly language code to make the actual
kernel request. This makes them convenient to use and portable
(the C libraries have to change from system to system, but C
programs don't).
When we refer to something like readdir()
as a
system call, we mean to imply that the function (or macro) does
relatively little work beyond making the one appropriate system
call, assembling the results, and returning.
We think of system calls as different from regular library
functions, such as round()
or
strcmp()
, that do all their work in user space.
(There are some library routines that involve quite a bit of
user-level code plus one or more system calls, most notably
those of the standard I/O library).
To use a system call, you should include the appropriate header file(s) (just as with regular library routines). The headers will define the necessary datatypes, function prototypes, and handy constants and macros.
To see what system calls a program runs, you can use the
Linux program strace
.
Error Handling
C does not have any standard exception signaling/handling mechanism, so errors are handled by normal function return values (or by side affecting some data). The hundreds of system calls available in Unix/Linux handle errors in a variety of ways, and, just as with library functions, you should study their documentation carefully so that you can catch and handle errors appropriately.
System calls that return a value often designate some special
value as indicative of an error. -1
is a common
error return value, but some return 0
or a
NULL
pointer or EOF
.
Many system calls and system-level functions use the
errno
facility. To deal with these calls, you will
need to include errno.h
, which will provide
something that looks like a global integer variable called
errno
. There are a standard set of predefined
constants corresponding to common error conditions (see
errno.h
for details).
You will see system call documentation that will say, for
example, that the call returns EOF
on error, and
the precise reason for the error will be left in
errno
. To use the errno
facility,
you:
- first make a system call, then
- check to see if it gave an error indication, then and only then
- use
errno
to determine and respond to the cause of the error.
errno
even if there is not an error, so you
must check for an error indication first.
There are two useful functions you may want to use in
conjunction with errno
: perror()
and
strerror()
. strerror()
takes an
integer argument (errno
) and returns a string that,
one hopes, gives a hint about what the error means.
perror()
takes an argument string which it prints
to standard error followed by the result of calling
strerror()
on the current value of
errno
.
Here is an example of a program that uses errno
and perror()
:
And here is a script of the errno_example
program
in action:
% errno_example Usage: errno_example <filename> % errno_example errno_example.c % errno_example non-existent-file Open: No such file or directory % echo $? 2 %
Modified: 14 February 2008