Kernel Stdio Theory

From OSDev.wiki
Revision as of 14:15, 27 August 2009 by osdev>Gravaera (New page: ==Standard Input/Output Theory== ===What is Standard Input/Output?=== Every kernel has an interface for an application to 'tie' itself to which allows it to read basic input from the use...)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Standard Input/Output Theory

What is Standard Input/Output?

Every kernel has an interface for an application to 'tie' itself to which allows it to read basic input from the user (Standard Input), and to provide a basic stream of output to the user (Standard Output).

In the Unix kernel, the Standard Output is the user's terminal device. (e.g: /dev/tty0). Try going into your Unix/Linux command prompt and typing who am i. This is the device that represents your current terminal's standard Output. On microcomputers (the one you're using right now) there are no terminals connected to huge mainframes, so the modern Linux/Unix microcomputers just create a terminal device anyway, and associate it with the Kernel's Standard Output.

Now: Try echo Hello from Std Output! >file This prints the string "Hello from Std Output" to a file called 'file', by redirecting the Standard Output to the file. Standard Output, henceforth referred to as Stdout, from the terminal screen directly to the file.

Go back and find out which terminal you are, by running either who am i or simply typing tty. Take the output from tty and place it at the end of the line, where 'file' was last time. My kernel reports my terminal as /dev/pts/1. Now try: echo Hello from Std Output! >/dev/pts/1

This time, you see the out put from 'echo' on the terminal. Why? You explicitly redirected the output of Stdout to your Stdout. /dev/pts/1 in my case, and whatever you got in yours, is synonymous with the standard output for the current user.

Interestingly, though, this file also acts as the Stdin device: reading from it causes all the characters you type at the keyboard to be reported to the program currently running program.

The unix cat command reads and outputs what it sees in a file. When you type at the keyboard, this is directed to Stdin, which applications may read from. To get a better understanding more quickly, try:

cat /dev/pts/1

Now keep typing words and characters, and then press enter when you feel like it. The characters you typed at the terminal are sent to Stdin, which cat is reading from. When you press 'enter', the kernel stops reading from the keyboard, having reached the end of line for the current bit of input, and sends this line of keyboard input to the Standard Input, which, currently, cat is reading from. Cat, thinking that it is reading from an ordinary file, does what it's supposed to do: echo the contents of the file onto the terminal.

When you're done typing lines, press Ctl+d, which is a synonym in *nix for "No more input/End of input". When dealing with files, this is synonymous for "End of file". The kernel receives the indication that there is no more input, and forwards this to the Stdin, which gives it to cat. cat interprets the "no more data" signal to mean that the end of the file it is currently reading has been reached. Just like any other file, it stops reading from the kernel. This is something common to all Unices, in that they treat everything as if it's nothing more than a normal file.

But we can understand that the dynamic nature of this file the terminal StdIO file indicates that it is obviously not a normal file on disk, but a link to a kernel API which manages Stdin and Stdout.

How can I implement StdIO in my kernel?

Short Discourse on Design Considerations

Most early developers do not take into account the fact that their kernel should implement some form of Standard Input/Output for applications. Two of the most early drivers that most OSDev-ers (not a word...) write are actually two drivers which should be part of a Standard Input/Output setup: The console driver, and the Keyboard Driver.

Now in most kernels, including the author's, implementing Stdout at boot time is relatively pointless: there are no applications to use it except for the kernel. Not only that, but Stdout must be tied to a screen output device.

From all indications, all OSDev-ers write a driver that directly references the VGA text mode Framerbuffer while booting. Of course, after boot, when the Graphical side of the kernel must come into play, many still don't write a Stdout interface because of lack of proper design.

One can generally assume that Stdout is the place that applications should be writing to so that their output characters can be seen on screen. In other words, every application should have its own Stdout interface.

Let's perform a neat experiment to understand what happens with the StdIO terminal file in *Nix: Open up two terminal windows under *Nix. On one terminal, type the command: cat /dev/pts/1 (or whatever your current terminal device is. From now on when I type /dev/pts/1 that's what I'm referring to) and press enter. You will see that Cat has begun reading from the terminal.

On the second one, type echo <Insert random phrase here>. Note that when the shell is reading input from the keyboard, it allows you to send non-printable characters by escaping them. If you type echo hello \<enter> Jane\<enter> I'm glad to meet you<enter> you'll find that the escaped <enter> keypresses do not cause the echo command to be processed, but that the shell interprets that as a literal LineFeed character and continues to read what characters to send to echo. The Linefeed will be sent to echo just as any other character would. So you can type stuff on multiple lines, too.

What we have here is a setup where cat is reading from the terminal, and echo is writing to it. Keep the window with cat open, and keep sending echo commands to the terminal.

You'll find that the window with cat is showing nothing. Now modify your echo commands to write directly to the terminal: echo <insert random phrase here> >/dev/pts/1.

What happens now? Yes. cat reads the characters that echo sends. So why didn't cat get them before? Every application has its own Stdout, so echo was writing to its Stdout, and not to the Terminal/System Stdout.

Returning to where we were before, I was stating that every application should have its own Stdout. However, there is generally only one Stdin device for any application: the keyboard. An efficient design for Stdin would be:

  • Execute a task. Have a global variable to indicate which process is the currently active process, and therefore would be reading from the user's keyboard input. (Note that i didn't say which is the currently executing process, but the currently active process. I.e: the one the user has open in front of him, where the currently active cursor is.
  • When the keyboard IRQ is raised, the Keyboard driver fetches the keystroke from the device, and appends it to the StdIn for the active process. The active process reads from StdIn, and gets the keys placed in its Stdin buffer. Question: But what about the other applications running in the background? Like if the user has a notepad open, and a Firefox where he is posting on a forum. The Firefox window is active.

Well, take some time to think about it a bit. The processor is constantly rotating timeslices between processes. Each process what needs to read from the keyboard is reading from Stdin. But currently Stdin is tied to the Active Application window process. So ONLY the Active process actually receives the keys entered at the keyboard, since the keyboard writes directly to the specific buffer of the Active process. Hmmm...well? What about the other process windows? Do they need to know what I'm typing in a textbox element on a webpage in Firefox? No. When I switch to their process, and they become the Active Process, then when they read from Stdin, then they'll receive the Keyboard's input, too.

Makes sense, right?

That's the basic rundown of a small part of the theory. Later additions should add more body, and even implementation details.