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?
CodePudding user response:
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.
CodePudding user response:
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