7

I have a big confusion regarding the system calls in OS. According to the book "operating systems concepts 9th ", it is mentioned (in page 63) that :

Most programmers never see this level of detail, however. Typically, application developers design programs according to an application programming interface (API).

Behind the scenes, the functions that make up an API typically invoke the actual system calls on behalf of the application programmer.

This means that, as a programmer, we don't use the system calls directly. However, I see videos that teach how to use system calls directly, like this one , where it accesses the read|() and write() system calls. So the system calls can be used directly or using APIs or using both ??

2
  • 10
    read and write in that tutorial are not system calls, they're a userspace libc API.
    – Chris Down
    Feb 20, 2022 at 17:28
  • @ChrisDown Despite wikipedia labeling read and write as system calls, I agree with you 100%. While those functions are not a part of the C standard library, they are a part of the POSIX library (which also is an API). Feb 21, 2022 at 15:40

4 Answers 4

14

Without additional context, it is not entirely clear what level of abstraction the quote is talking about. However, if it is talking about operating system design concepts, it may be talking about an even lower layer.

Have you ever asked yourself what actually happens when you call write()? The system library will potentially do some sanity-checking on the values, and then likely end up handing them off to the operating system kernel.

Here is where you start to get really deep into the weeds. How exactly it does this will depend on your operating system, and even the particular processor architecture it's running on. For example, Linux internally uses syscall() to signal a system call to the kernel. But once again you might rightfully ask -- what does syscall() now do? Very roughly, it stores your parameters in standardized form somewhere, then runs a special processor instruction that switches to privileged mode and jumps to a syscall handler in the OS kernel, somewhere.


Now there's nothing stopping you from cutting out all of these middlepeople, simply putting your arguments in the right processor registers, and running this instruction yourself. There's no rule saying you have to use write(), or even syscall(). These functions are just features of convenience, because syscall() will work on every Linux, regardless of processor; and write() will work on any machine, regardless of operating system.

I suspect that this may be what your book is talking about, if it's talking about operating systems design. You, as a developer, don't need to use these functions, but in the overwhelming majority of situations you want to. However, under the hood these functions themselves had to be implemented by the designers for your operating system's standard library. They are, themselves, APIs -- standardized interfaces that prevent you from having to deal with processor internals.

11

The API which invokes the system call is written in code, such as a mixture of C and inline assembly. You can put that same, or analogous code into an application, if you are so inclined.

This is very rarely done. The technique is used in demonstration programs for showing how small a completely self-contained executable file can be with no library dependencies, yet do something useful.

Someone working on a run-time for a programming language that isn't C might opt to use raw system calls to avoid a dependency on the C library.

In the GNU/Linux world, the kernel and user space are almost entirely independent projects. It's conceivable to have a situation whereby some useful system call has been developed that an application wants to use, but the application has to run in systems whose C library is older and doesn't expose that system call as an API (yet whose kernel is newer and has the system call). In that situation, the only way the application can use the system call is to issue it itself.

There can be situations in which the API doesn't directly correspond to the underlying system calls, and for various reasons such as performance, the application developers decide to take those system calls into their own hands.

For instance, on GNU/Linux, the POSIX functions opendir and readdir, for opening a stream-like object over a directory and reading directory entries one by one, is implemented as getdents system call: a function for reading an entire batch of directory entries into an array. Someone might be interested in using such a thing directly rather than through the one-by-one API.

The manual page for getdents cautions:

SYNOPSIS
   int getdents(unsigned int fd, struct linux_dirent *dirp,
                unsigned int count);
   int getdents64(unsigned int fd, struct linux_dirent64 *dirp,
                unsigned int count);

[...]

NOTES
   Glibc does not provide a  wrapper  for  these  system  calls;  call  them  using
   syscall(2).   You  will need to define the linux_dirent or linux_dirent64 struc‐
   ture yourself.  However, you probably want to use readdir(3) instead.
8

Typically, application developers design programs according to an application programming interface (API).

This means that, as a programmer, we don't use the system calls directly.

No, that means you typically don't use the system calls directly. You can use them, but when programming you usually use some higher level library and use functions from its API instead of system calls.

For example if you are writing a Gtk application, you'll use g_file_set_contents to write to a file instead of using write directly, simply because it is easier to use.

But nothing is stopping from using the system call even if some higher level is available if you think it is better suited for the task you are working on.

This usually depends on what kind of application or library you are working on. If you are programming a new low level library or a system tool, you'll probably use the system calls directly. If you are working on a new GUI application, you'll probably use the API provided by Gtk or Qt. And if you are using some higher level programming language, you'll probably use its API, like the built-in open in Python for example.

1
  • 5
    There are a few "system calls" which have equivalent libc wrappers. E.g. man -s 2 fork has a note that glibc has a fork() wrapper that invokes clone() instead (maybe only in some situations). Feb 20, 2022 at 9:23
3

However, I see videos that teach how to use system calls directly, like this one, where it accesses the read|() and write() system calls.

Despite the fact that wikipedia also calls read and write system calls, I would never think of them as such, and I suspect the author of "Operating System Concepts" you quoted would agree with me. Those functions are instead members of the POSIX API. Your C code that uses those functions will be portable across POSIX-compliant machines. The API hides the machine- and device-dependent nature of those functions. The implementations of read and write will vary across machines, and they will almost certainly will be system calls in those implementations. But that does not mean that read and write are system calls.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .