Linux Kernel Architecture

(Jacob Rumans) #1

Chapter 13: System Calls....................................................


13.1 Basics of System Programming


Principally, system programming involves work with the standard library that provides a wide range of
essential functions for developing applications. No matter what kind of applications they write, program-
mers have to know the basics of system programming. A simple program such as the classichello.c
routine, which displays ‘‘Hello, world!‘‘ or a similar text on screen, makes indirect use of system routines
to output the necessary characters.

Of course, system programming need not always be done in C. There are other programming
languages — such as C++,Pascal,Java,oreventhedreadfulFORTRAN — which also support the more
or less direct use of routines from external librariesand are therefore also able to invoke standard library
functions. Nevertheless, it is usual to write system programs in C simply because this fits best into the
Unixconcept — allUnixkernels are written in C, and Linux is no exception.

The standard library is not only a collection of interfaces to implement the kernel system calls; it also
features many other functions that are implemented fully in userspace. This simplifies the work of pro-
grammers, who are spared the effort of constantly reinventing the wheel. And the approximately 100 MiB
of code in the GNU C library must be good for something.

Because the general programming language trend is toward higher and higher levels of abstraction, the
real meaning of system programming is slowly being eroded. Why bother with system details when suc-
cessful programs can be built effortlessly with a few mouse clicks? A middle course is required. A short
Perl script that scans a text file for a certain string will hardly want to bother with the mechanisms that
open and read the text file. In this situation, a pragmatic view that somehow the data will be coaxed out of
the file is sufficient. On the other hand, databases with gigabytes or terabytes of data will certainly want
to know which underlying operating system mechanisms are used to access their files and raw data so
that the database code can be tuned to deliver maximum performance. Supplying a giant matrix in mem-
ory with specific values is a classic example of how program performance can be significantly boosted
by observing the internal structures of the operating system. The order in which values are supplied is
crucial if the matrix data are spread over several memory pages. Unnecessary paging can be avoided and
system caches and buffers can be put to best use depending on how the memory management subsystem
manages memory.

This chapter discusses techniques that are not (or at least only to a minor extent) abstracted from the
functions of the kernel — all the more so as we want to examine the internal structure of the kernel and
the architectural principles used, including the interfaces to the outside world.

13.1.1 Tracing System Calls


The following example illustrates how system calls are made using the wrapper routines of the standard
library:

#include<stdio.h>
#include<fcntl.h>
#include<unistd.h>
#include<malloc.h>

int main() {
int handle, bytes;
void* ptr;
Free download pdf