What is meant by "a system call" if not the implementation in the programing language?

6,462

Solution 1

System calls per se are a concept. They represent actions that processes can ask the kernel to perform.

Those system calls are implemented in the kernel of the UNIX-like system. This implementation (written in C, and in asm for small parts) actually performs the action in the system.

Then, processes use an interface to ask the system for the execution of the system calls. This interface is specified by POSIX. This is a set of functions of the C standard library. They are actually wrappers, they may perform some checks and then call a system-specific function in the kernel that tell it to do the actions required by the system call. And the trick is that those functions which are the interface are named the same as the system calls themselves and are often referred directly as "the system calls".

You could call the function in the kernel that perform the system call directly through the system-specific mechanism. The problem is that it makes your code absolutely not portable.

So, a system call is:

  • a concept, a sequence of action performed by the kernel to offer a service to a user process
  • the function of the C standard library you should use in your code to get this service from the kernel.

Solution 2

A system call is a way to ask your operating system (kernel) to do some operation on behalf of your program, that the program can't do by itself (or is just inconvenient). The reason for not being able to do some operation is normally that allowing a random program to do them might compromise the integrity of the system, like doing I/O (directly to RAM, overwriting anything).

POSIX defines an interface for programs, certain functions that your program can call. Some of those translate more or less directly to system calls, others require more elaboration. It is the runtime for your language, e.g. the C library, who is responsible for offering the POSIX interface, and to package arguments and receive results back to hand to the caller.

Unixy systems offer POSIX interfaces more or less directly as system calls. Typically there is a way to invoke system calls directly, look for syscall(2) for the details on how to use this facility in Linux.

Solution 3

Sure, let's do the how-many-directions-can-we-look-at-this-elephant-from? thing.

The actual system call is, in your built program, the machine instruction that triggers the privilege escalation into kernel mode, and in the kernel itself it's the code that instruction invokes. The libc code (and every language runtime) sets up the machine registers and in-storage parameters where the kernel code expects to find them, which can be decidedly odd places due to constraints on that machine instruction.

Once in the OS code itself, there's a bit of mirror-image unwinding of the machine-specific stuff the userland runtime did and then a perfectly ordinary subroutine call.
If you want to see exactly how this works in a full-scale OS, pull the kernel source (git clone https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/) and do e.g. git grep -i system\ call. Pull the glibc source and do likewise.

Solution 4

In Linux at least the system call mechanism works under most architectures by placing some specifically formatted data (usually some kind of c struct) in either some registers or predefined memory addresses.

The issue comes however in actually forcing the CPU to do the switch into kernel space so it can run the privileged kernel code to service the call. This is done by forcing a fault of some sort (a fault being a divide by 0, an undefined overflow or a segfault, etc) this forces the kernel to take over execution to handle the fault.

Normally the kernel handles faults by either killing the causing process or running a user supplied handler. However in the case of a syscall it will instead check the predefined registers and memory locations and if they contain a syscall request it will run that using the data provided by the user process in the in-memory struct. This usually has to be done with some specially hand crafted assembly and to ease the use of the syscall for the user the system's C library has to wrap it as a function. For a lower level interface please see http://man7.org/linux/man-pages/man2/syscall.2.html for some information on how syscalls work and how you can call then without a C wrapper.

This is given an oversimplification, it is not true in all architectures (mips has a special syscall instruction) and not necessarily working the same on all OSes. Still, if you have any comments or questions please ask.

Amended: Note, regarding your comment about things in /dev/ this is actually a higher level interface to the kernel, not a lower one. These devices actually use (about) 4 syscalls underneath. Writing to them is the same as a write syscall, reading a read syscall, open/closing them equivalant to the open and close syscalls and running an ioctl causes a special ioctl syscall which in itself is an interface to access one of the system's many ioctl calls (special, usually device specific calls with too narrow usage to write a whole syscall for them).

Solution 5

Every system call has a associated integer. This integer number is a function of return value of the system call, number of arguments to the system call and type of the arguments. This system call number is nothing but a offset into global system call vector, this vector which is accessible only in privileged mode contains pointer to appropriate handlers. The process upon invoking a system call, a software interrupt(trap interrupt) would be generated, hence a trap handler would be run which determines which system call should be invoked. Then the kernel would copy the arguments of the system call passed by the user which is on the stack into the processor registers, and upon completing the service requested, data would be copied back into stack from the processor registers. This is one of the reason why there are limited arguments to system calls, since the arguments would be copied into processor registers and processors have limited registers.

Share:
6,462
TheMeaningfulEngineer
Author by

TheMeaningfulEngineer

I like to think of myself as a Hardware/Software guy who will gladly discuss referential transparency during a code review and the next moment take a circular saw to build a casing for a self made power supply. My main interest can be summarized into Linux related software development, low power electronics and general DIY projects.

Updated on September 18, 2022

Comments

  • TheMeaningfulEngineer
    TheMeaningfulEngineer almost 2 years

    I would like to understand the term "system call". I am familiar that system calls are used to get kernel services from a userspace application.

    The part i need clarification with is the difference between a "system call" and a "C implementation of the system call".

    Here is a quote that confuses me:

    On Unix-like systems, that API is usually part of an implementation of the C library (libc), such as glibc, that provides wrapper functions for the system calls, often named the same as the system calls that they call

    What are the "system calls that they call"? Where is their source? Can I include them directly in my code?

    Is the "system call" in a generic sense just a POSIX defined interface but to actually see the implementation one could examine the C source and in it see how the actual userspace to kernel communication actually goes?

    Background note: I'm trying to understand if, in the end, each c function ends up interacting with devices from /dev.

  • TheMeaningfulEngineer
    TheMeaningfulEngineer about 10 years
    Do you have an example of the "wrapper function" and a actual system call? (file paths in Linux or links to sources)
  • lgeorget
    lgeorget about 10 years
    For example, this is the implementation of the getpid system call in the Linux kernel: lxr.free-electrons.com/source/kernel/timer.c?v=2.6.35#L1337. And this is the wrapper function in the GNU C standard library glibc-2.19: fossies.org/dox/glibc-2.19/….
  • Scott - Слава Україні
    Scott - Слава Україні about 10 years
    You touch on an important point that the other answers just brush up against. Any function that a reasonably capable programmer could write for himself (such as strlen, strcpy, sqrt, and qsort) can be and probably is in user space, loaded from a library. (Mostly libc; math functions like sqrt and the trigonometric and hyperbolic functions are probably in libm, the math library.) … (continued)
  • Scott - Слава Україні
    Scott - Слава Україні about 10 years
    (continued) … But there’s no way a user can write his own fork, kill, or open function, because these require access to the operating system kernel memory space (e.g., the process table) or privileged instructions (e.g., I/O). Therefore the code that performs these functions must be in the operating system kernel; hence, system functions or system calls.
  • vonbrand
    vonbrand over 8 years
    True, but rummaging around in Linux or glibc is a bit on the heavy side...
  • vonbrand
    vonbrand over 8 years
    Each call (operation) is internally identified by a number, true. But the number depends on the operation, not on return value nor number of arguments. An explanation of how it used to work from userland on x86 is here
  • rchard2scout
    rchard2scout almost 5 years
    @Igeorget: your links no longer work. Updated link for the kernel implementation: github.com/torvalds/linux/blob/…. I couldn't find what glibc does these days, that code is impossible to navigate.
  • java_doctor_101
    java_doctor_101 over 2 years
  • lgeorget
    lgeorget over 2 years
    @nitinsh99 Thank you, that answer is already 7 year old, links die fast..