1

I ask this, because I am getting very conflicting definitions of System calls.

One one hand, I have seen the definition that they are an API the OS provides that a user program can call. Since this API is a high level interface, it has to be implemented in a high level language like C.

On the other hand, I have seen that the actual OS syscalls are machine instructions, for which you have to set certain registers to call (according to some compliance standard set by the OS). But this looks nothing like the UNIX APIs like open(), write() and read(), so what is going on here.

I have also read that these high level interfaces are implemented in the C libraries which do the actual assembly code syscalls. In that case, why do we say the OS provides this interface when it is actually provided by the C language. What if I want to perform a UNIX syscall directly to the OS without having to use C?

Saad Haider
  • 183
  • 5
  • 3
    Linux is open source. gnu libraries are open source. What is stopping you from checking? It is simple and will give you the answer. – 0___________ Aug 28 '21 at 16:54
  • Not using the standard C library is usually foolish. If you really needed avoiding to do so, you would probably also know how to do it. – Cheatah Aug 28 '21 at 16:56
  • 1
    *`What if I want to perform a UNIX syscall directly to the OS without having to use C?`* You can. You can also write the whole application in assembler. But the question is what for? Why? What do you want to achieve? For educational purposes - yes, for real life programming - never – 0___________ Aug 28 '21 at 17:04
  • Yes I know we shouldn't, I just wanna know how things are done on the lower level, and what exactly are the interfaces the OS provides – Saad Haider Aug 28 '21 at 17:20
  • There's hardly any point in writing anything in Assembly these days. Writing Assembly is the compiler's job. Even microcontroller programming is done in either C or some pseudo-C language. The notion that Assembly is faster than C is completely outdated, modern compilers do a far better job at optimizing code than you do. – Havenard Aug 28 '21 at 17:43
  • 1
    "Since this API is a high level interface, it has to be implemented in a high level language like C." No, it just means that the library has to use an ABI that other higher-level languages can interact with. Typically, the OS itself is compiled from C source. – chepner Aug 28 '21 at 18:33

3 Answers3

4

There are two open functions - one, the syscall open exposed by the operating system (e.g. Linux), and two, the C-library function open, exposed by the C standard library (e.g. glibc).

You can see two different man pages for these functions - run man 2 open to see the man page regarding the syscall, and man 3 open to see the man page regarding the C standard function.


Functions you mentioned like open, write, and read can be confusing - because they exist both as syscalls and as C standard functions. But they are separate entities entirely - in fact, glibc's open function doesn't even use the open syscall - it uses the openat syscall.

On Windows, where the syscall open doesn't even exist - the C standard library function open does still exist, and uses WinAPI's CreateFile behind the scenes.


What if I want to perform a UNIX syscall directly to the OS without having to use C?

This is possible - indeed, glibc has to do it to implement C standard library functions. But it's tricky, and involves implementing wrappers for the syscalls and sometimes even handcrafting assembly.


If you want to see things for yourself, you can look at how glibc implements open:

int
__libc_open (const char *file, int oflag, ...)
{
  int mode = 0;
  if (__OPEN_NEEDS_MODE (oflag))
    {
      va_list arg;
      va_start (arg, oflag);
      mode = va_arg (arg, int);
      va_end (arg);
    }
  return SYSCALL_CANCEL (openat, AT_FDCWD, file, oflag, mode);
}
...
weak_alias (__libc_open, open)

notice that the function ends with a call to the macro SYSCALL_CANCEL, which will end up calling the OS-exposed openat syscall.

Daniel Kleinstein
  • 5,262
  • 1
  • 22
  • 39
2

Are OS libraries written in assembly or in C

That is a question that can not really be answered as it depends. Technically there are no limitations on the implementation (i.e. it can be written in any language, though C is probably the most common followed by assembly).

The important part here is the ABI. This defines how OS calls can be made.

You can make system calls in assembly (if you know the ABI you can manually write all the code to comply), the C compiler knows the ABI and will automatically generate all the code required to make a call.

Most languages though allow you to make system calls, they will either know the ABI or have a wrapper API that translates the calls from a language call to the appropriate ABI for that OS.


I ask this, because I am getting very conflicting definitions of System calls.

The definitions will depend on the context. You will have to give examples of what the definitions are AND in what context they are being used.


One one hand, I have seen the definition that they are an API the OS provides that a user program can call.

Sure this is one way to look at it.

More strictly I would ays the OS provides a set of interfaces that can be used to perform privileged tasks. Now those interfaces can be exposed via an API provided by a particular environment that makes them easier to use.


Since this API is a high level interface, it has to be implemented in a high level language like C.

Sort of true.

An environment can expose an API does not mean that it needs a high level language (and C is not a high level language, it is one step above assembly, it is considered a low level language). And just because it is exposed by the language does not mean it is implemented in that language.


On the other hand, I have seen that the actual OS syscalls are machine instructions, for which you have to set certain registers to call (according to some compliance standard set by the OS).

OK. Here we have moved from System Calls to syscalls. We should be very careful on how we use these terms to make sure we are not conflating different terms.

I would (and this is a bit abstract still) think about the computer as several levels of abstraction:

                      Hardware 
        ------        --------------
                      syscalls
          OS          --------------
                      System Calls       (read/write etc..)
        ------        --------------
                      Language Interface (read/write etc..)

You can poke the hardware directly if you want (if you know how), but it is better if you can make syscalls (if you know how), but it better to use the OS System Calls which use a well defined ABI, but it better to use the language interface (what you would call the API) to call the underlying System Calls.


But this looks nothing like the UNIX APIs like open(), write() and read(), so what is going on here.

Here the UNIX OS provides the open/close/read interface.

The C libraries provides a very thin API wrapper interface above the the OS System Calls. The C compiler will then generate the correct instructions to call the System Calls using the correct ABI, which in turn will call the next layer down in the OS to use the syscalls.


I have also read that these high level interfaces are implemented in the C libraries which do the actual assembly code syscalls.

The high level interface can be written in any language. But the C one is so easy to use that most other languages don't bother doing it themselves but simply call via the C interface.

Martin York
  • 257,169
  • 86
  • 333
  • 562
  • Thank you so much for such a detailed answer! I have one further question. How do I call a system call of an operating system directly without going through the C wrapper function. For example, I want to call the OS's (Linux in this case) read(fd, buf, count), not the C library's wrapper version. How do I do this? It has to exist right since Linux clearly states that it provides this API to call the read function as so. – Saad Haider Aug 28 '21 at 18:52
  • 1
    Knowing it is `Linux` is not enough. You need to understand the **ABI** the OS uses on your particular hardware (Note there is no standard ABI this is something you would have to research). You will have to find appropriate documentation. Note The C API is there for a reason. By manually calling the OS you are removing one layer of abstraction that makes your code less portable and more brittle to change; also the overhead added by the C API is probably not significant so there are serious downsides but no significant upsides to doing this. – Martin York Aug 28 '21 at 20:28
  • Ah I see. I know it is not a great idea to do so, but I was just curious how the OS provides this service. Thanks so much! – Saad Haider Aug 29 '21 at 07:17
1

It's VERRRY rare to ever directly write something in assembly. By writing in C you can compile it for many different CPU architectures whereas by writing in assembly you are basically stuck with one specific architecture. Most operating systems are written in C. We say the OS provides the interface because you are interacting with the operating system which happens to be written in C.