0

I am trying to learn some C, but I am finding some of the standard functions a bit opaque.

Take putc or putchar as an example. I am trying to work out what drives this at the most basic level. I have tried to follow their definitions back through the GNU compiler source but it just ends up in this enormous tree of source files.

Is there a primitive "print this character" function that all the others are built from? I had assumed that it was just a write() system call, but an answer to a related question said that this is completely implementation specific. So how else can it actually produce the output if not a system call?

Luke
  • 145
  • 5
  • Maybe something [like this](https://code.woboq.org/userspace/glibc/libio/putchar.c.html) ? – Paul T. Mar 27 '22 at 02:42
  • 1
    Yes, it's implementation-specific, but both Unix and Windows have `write()`, so most implementations use that. – Barmar Mar 27 '22 at 02:42
  • try looking at `putchar` implementation. It should be simpler. – bolov Mar 27 '22 at 02:43
  • Note that `putc` and `putchar` are likely to be implemented as macros that update the output buffer, and then call into something internal that flushes the buffer if necessary. That's where the actual writing takes place. – Barmar Mar 27 '22 at 02:44
  • @PaulT. Where is the definition of `_IO_putc_unlocked` that it calls? – Barmar Mar 27 '22 at 02:46
  • That is a macro defined [here](https://code.woboq.org/userspace/glibc/libio/libio.h.html#_M/_IO_putc_unlocked), which calls another macro defined [here](https://code.woboq.org/userspace/glibc/libio/bits/types/struct_FILE.h.html#_M/__putc_unlocked_body). The page has a search that can be used to find other code that I just used to find those two. – Paul T. Mar 27 '22 at 03:07
  • Students in the same class: [one](https://stackoverflow.com/questions/71633306/how-do-c-output-functions-actually-work-under-the-hood), [two](https://stackoverflow.com/questions/71634992/definition-of-inbuilt-c-functions), [three](https://stackoverflow.com/questions/71634030/how-puts-standard-library-function-works-in-c). – Eric Postpischil Mar 27 '22 at 11:25

2 Answers2

3

So how else can it actually produce the output if not a system call?

It does use a system call, but the specific system call is implementation-dependent.

Unix implementations use the write() system call. Implementations for other operating systems will use whatever is analogous to this.

There could also be standalone implementations that run directly on hardware without an operating system. These "unhosted" implementations might omit the stdio library, or they could implement its features by accessing the hardware directly. In this case there's no system call, the I/O is done by the stdio library itself.

Barmar
  • 741,623
  • 53
  • 500
  • 612
1

For Unix based systems for which Linux is part, most functions in stdio library are wrappers that are one layer above the standard I/O system calls. You see, the operating system provides a set of APIs called system calls. Applications cannot directly access hardware resources and hence they usually call these "system calls" whenever they need to do any sort of privileged thing like writing to the screen or reading from the keyboard.

In Unix, everything is abstracted as a file so whenever you need to write characters to a screen, all you need to do is open some file that represents the "screen" and write those characters there. The kernel will take care of the rest. Quite simply, this is how you'd do this in C:

#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>

#define BUFF_SIZE 2

int main()
{

    int terminal;
    char buffer[BUFF_SIZE] = "C\n";        // This will store the character to print +  new line
    terminal = open("/dev/tty", O_WRONLY); // systemcall to open terminal
    if (terminal < 0)
        exit(1); // some error happened

    dup2(terminal, STDOUT_FILENO); // use our newly opened terminal as default Standard output

    if (write(terminal, buffer, BUFF_SIZE) != BUFF_SIZE) // systemcall to write to terminal
        exit(1);                                         // We couldn't write anything
}

This just goes to show you that everything in stdio is layered on top of the basic I/O system calls. These system calls are read, write, open, etc. If you want to learn more about system calls and some OS internals, read the book "Three Easy Pieces" by Andrea Arpaci-Dusseau

  • This is exactly the kind of answer I was looking for, thank you! I will definitely check out that book. – Luke Mar 27 '22 at 03:43