.. _Syscall:

.. raw:: html

   <script>ODSA.SETTINGS.DISP_MOD_COMP = true;ODSA.SETTINGS.MODULE_NAME = "Syscall";ODSA.SETTINGS.MODULE_LONG_NAME = "System Call Interface";ODSA.SETTINGS.MODULE_CHAPTER = "Processes and OS Basics"; ODSA.SETTINGS.BUILD_DATE = "2021-06-14 17:15:25"; ODSA.SETTINGS.BUILD_CMAP = false;JSAV_OPTIONS['lang']='en';JSAV_EXERCISE_OPTIONS['code']='java';</script>


.. |--| unicode:: U+2013   .. en dash
.. |---| unicode:: U+2014  .. em dash, trimming surrounding whitespace
   :trim:


.. This file is part of the OpenCSF eTextbook project. It was
.. auto-generated by scripts from the OpenDSA eTextbook project.
.. See https://OpenCSF.org for more details. OpenCSF is distributed
.. under a Creative Commons Attribution-NonCommercial 4.0 International
.. License (see http://creativecommons.org/licenses/by-nc/4.0/),
.. Copyright (c) 2019-2021 by Michael S. Kirkpatrick. OpenDSA is
.. distributed under an MIT open source license, Copyright (c) 2012-2021
.. by the OpenDSA Project Contributors.

.. avmetadata::
   :author: Michael S. Kirkpatrick
   :requires:
   :satisfies: System Call Interface
   :topic: 

System Call Interface
=====================

User-mode programs can execute standard CPU instructions that are focused on performing a
calculation or implementing a logical control flow. However, user-mode programs have no direct
access to any shared computing resource outside the CPU. For instance, user-mode software cannot
read data from a hard drive, send data across a network interface, or even display information to
the monitor screen. Instead, the user-mode program must execute a system call to request the kernel
perform this action on its behalf.

System Calls vs. Function Calls
-------------------------------

At the level of assembly language, a system call involves executing a trap instruction. In modern
x86 code, the trap instruction is ``syscall`` [#f10]_ , which acts in a manner analogous to call.
Instead of jumping to a function within the same program, though, ``syscall`` triggers a mode switch
and jumps to a routine in the kernel portion of memory. The kernel validates the system call
parameters and checks the process's access permissions. For instance, if the system call is a
request to write to a file, the kernel will determine whether the user running the program is
allowed to perform this action. Once the kernel has finished performing the system call, it uses the
``sysret`` instruction, which performs a role similar to the standard ``ret`` instruction. The
difference is that sysret also changes the privilege level, returning the system to user mode.

From a higher level perspective, system calls are often written to look like standard C functions.
For instance, it is common to find references to the ``write()`` system call. This practice is
simply a form of short-hand notation. In most cases, there is a C function that acts as a wrapper
for the system call. That is, there is a C function called ``write()`` in the C standard library;
this function will perform a few initial steps before triggering the ``syscall`` trap instruction.
To be clear, there is a distinction between the ``write()`` C function and the system call, but this
distinction is often blurred in practice.

Linux System Calls
------------------

The Linux source code repository contains the full list of Linux system calls. [#f11]_ This table
identifies the mapping between the system call number (which actually specifies the system call),
the name that is commonly used, and the entry point routine within the Linux kernel itself. For
instance, system call 0 is the ``read()`` system call. When a user-mode program executes the
``read()`` system call, the system will trigger a mode switch and jump to the ``sys_read()``
function within the Linux kernel.

There are a couple of observations that can be made from this table. First, every system call has a
unique number associated with it. As we will explain next, x86 system call mechanics only use this
number. The name that associated with each number is just to give meaning to the programmer, just as
we use function names instead of relying on memorization of hard-coded addresses. Second, the names
of the entry point functions in Linux are the names of the system calls with ``sys_`` prepended; for
instance, the ``open()`` system call will call the ``sys_open()`` function in the kernel, and
``mmap()`` will call ``sys_mmap()``.

Lastly, note that the names of the system calls correspond to many common C standard library
functions. For instance, ``open()`` and ``close()`` are the system calls that are used to establish
connections to files, ``socket()`` is the system call to create a socket for network communication,
and ``exit()`` can be used to terminate the current process. That is, many C functions are simply
wrappers for system calls.

In contrast, many C functions are implemented to provide additional functionality on top of system
calls. In the case of ``printf()``, the code will eventually trigger the ``write()`` system call.
The primary difference is that ``write()`` requires low-level details of how the system is being
used that ``printf()`` abstracts away. In addition, calling ``write()`` requires exact knowledge of
the length of the message to be printed, whereas ``printf()`` does not. In summary, many C standard
library functions provide a thin wrapper for invoking system calls, while other functions do not.

`Table 2.1 <#tbl2-1>`_ lists a small sample of the more than 300 system calls available on 64-bit Linux systems.
The full list of system calls can be found in the ``syscalls(2)`` man or in ``<asm/unistd_64.h>``,
which is included (through a nested sequence of headers) by ``<sys/syscall.h>``. [#f12]_ Each system
call is documented in a section 2 man page [#f13]_ (e.g., ``man 2 read``).

.. _tbl2-1:

.. raw:: html

   <center>
   <div class="row">
   <div class="col-12">
   <table class="table table-bordered">
     <thead class="jmu-dark-purple-bg text-light">
       <tr>
         <th class="py-0 center">Syscall</th>
         <th class="py-0 center">Number</th>
         <th class="py-0 center">Purpose</th>
       </tr>
     </thead>
     <tbody>
       <tr>
         <td class="py-0"><code>read</code></td>
         <td class="py-0">0</td>
         <td class="py-0">Read from a file descriptor</td>
       </tr>
       <tr>
         <td class="py-0"><code>write</code></td>
         <td class="py-0">1</td>
         <td class="py-0">Write to a file descriptor</td>
       </tr>
       <tr>
         <td class="py-0"><code>nanosleep</code></td>
         <td class="py-0">35</td>
         <td class="py-0">High-resolution sleep (units in seconds and nanoseconds)</td>
       </tr>
       <tr>
         <td class="py-0"><code>exit</code></td>
         <td class="py-0">60</td>
         <td class="py-0">Terminate the current process</td>
       </tr>
       <tr>
         <td class="py-0"><code>kill</code></td>
         <td class="py-0">62</td>
         <td class="py-0">Send a signal to a process</td>
       </tr>
       <tr>
         <td class="py-0"><code>uname</code></td>
         <td class="py-0">63</td>
         <td class="py-0">Get information (name, release, etc.) about the current kernel</td>
       </tr>
       <tr>
         <td class="py-0"><code>gettimeofday</code></td>
         <td class="py-0">96</td>
         <td class="py-0">Get the system time (in seconds since 12:00 AM Jan. 1, 1970)</td>
       </tr>
       <tr>
         <td class="py-0"><code>sysinfo</code></td>
         <td class="py-0">99</td>
         <td class="py-0">Get information about memory usage and CPU load average</td>
       </tr>
       <tr>
         <td class="py-0"><code>ptrace</code></td>
         <td class="py-0">101</td>
         <td class="py-0">Trace another process's execution</td>
       </tr>
     </tbody>
   </table>
   <p>
   Table 2.1: A sample of common Linux system calls
   </p>
   </center>
         

Calling System Calls in Assembly
--------------------------------

In assembly language, a system call looks almost exactly like a function call. Arguments are passed
to the system call using the general purpose registers and the stack as needed. The main difference
is that the system call number is stored into the ``%rax`` register. As an example, we can write a
standard "Hello, world" program in assembly language using two system calls.

In `Code Listing 2.3 <#cl2-3>`_, the four mov instructions (lines 9 – 12) set up the arguments for the
``write()`` system call, which expects three arguments: the file handle to write to, the address of
the message to write, and the length of the message in bytes. As with a normal function, these are
passed in the ``%rdi``, ``%rsi``, and ``%rdx`` registers. In a normal function call, the ``call``
instruction would specify the function to execute. However, ``syscall`` does not encode this
information. Instead, on line 5, we moved the constant 1 into ``%rax``, as this is the number for
the ``write()`` system call. Similarly, lines 16 and 17 indicate that the ``exit()`` system call
should be invoked with the value 0 as a parameter.

.. _cl2-3:

.. codeinclude:: Processes/CodeListing-2.3.s
   :linenos: true

Many system calls have return values that can be used to determine if an error occurred. As with
standard functions, the kernel puts return values in the ``%rax`` register. Negative values in the
range of -4095 to -1 indicate an error.

Calling System Calls with syscall()
-----------------------------------

Another method for invoking Linux system calls directly is to use ``syscall()``. For instance, the
program in `Code Listing 2.4 <#cl2-4>`_ shows the C equivalent of the assembly language code shown in Code
Listing 2.3. As before, we can bypass the C standard library functions for ``write()`` and
``exit()`` by invoking the system call directly. Specifcally, lines 12 and 13 make two system calls,
although they look like standard function calls. The C compiler will translate these into the
sequence of instructions in lines 9 – 13 and 16 – 18 from `Code Listing 2.3 <#cl2-3>`_.

.. _cl2-4:

.. codeinclude:: Processes/CodeListing-2.4.c
   :linenos: true

One aspect to note about the implementation of ``syscall()`` is that its parameters get passed in
the wrong registers. Specifically, the compiler mostly treats ``syscall()`` as a regular function
call, but it passes the first parameter in ``%rdi`` instead of the standard ``%rax``, because the
kernel expects the system call number to be in ``%rdi``. `Code Listing 2.5 <#cl2-5>`_ shows how Linux implements
``syscall()``, shifting the register values as needed (lines 9 – 13) and invoking the ``syscall`` instruction.

.. _cl2-5:

.. codeinclude:: Processes/CodeListing-2.5.s
   :linenos: true

.. [#f10] The ``syscall`` instruction is the primary trap instruction in 64-bit x86 systems. Earlier
   x86 programs performed system calls by triggering an interrupt with the ``int $0x80`` instruction;
   the kernel would use ``iret`` to return from the interrupt. For performance reasons, this approach
   was replaced with the ``sysenter`` and ``sysexit`` instructions on 32-bit systems. ``syscall`` and
   ``sysret`` are the 64-bit equivalent of these faster system call instructions.

.. [#f11] See https://github.com/torvalds/linux/blob/v3.13/arch/x86/syscalls/syscall_64.tbl for example.

.. [#f12] To prevent naming collisions, the names of the system calls are more complicated than
   shown in the table. Specifically, the ``Read()`` system call is listed in this table as ``__NR_read``.

.. [#f13] For readers new to man pages, documentation on this system can be found by typing ``man
   man`` on the command line. In brief, on Linux and UNIX systems, all C libraries are documented
   through this manual. The manual is divided into several sections, with section 2 used for system
   calls and section 3 used for the C standard library. The section of the manual for a function is
   noted in parentheses after the name. For instance, ``exit(2)`` documents on the exit system call,
   whereas ``exit(3)`` documents the standard C library ``exit()`` function. (Note there is a difference!)

.. avembed:: Exercises/Processes/KernelSyscallSumm.html ka
   :module: Syscall
   :points: 1.0
   :required: True
   :exer_opts: JXOP-debug=true&amp;JOP-lang=en&amp;JXOP-code=java
   :long_name: System call questions
   :threshold: 2

