Page 1 of 1

Wrote a skeleton page with basic Std Input/Output Theory

Posted: Thu Aug 27, 2009 8:20 am
by gravaera
http://wiki.osdev.org/Kernel_Stdio_Theory

When I have more time, I'll write up on some implementation details, such as how to write a Keyboard Driver that is compatible with a StdInput resource, etc. But that's just some basic theory. I wrote it because most people don't consider the design of their kernels much further than the here and now.

So: right now, I need a keyboard driver. But later on, my applications will need a StdInput device, and I'll have to rewrite it.

Please feel free to add to it.

Good luck in your Projects.
-gravaera.

Re: Wrote a skeleton page with basic Std Input/Output Theory

Posted: Thu Aug 27, 2009 9:12 am
by Solar
Erm...

I didn't read the whole text thoroughly, but it seems you're suggesting stdin and stdout being somewhat special, like, stdin always coming from the keyboard, and stdout always going to the screen.

If that observation is correct, you got it completely wrong.

stdin and stdout (and stderr...) are defined, by the C language standard, to be streams. From a userspace C application's view, there is no difference, technically, between:

Code: Select all

printf( "foo" );
and

Code: Select all

fprintf( stdout, "foo" );
and

Code: Select all

FILE * fh = fopen( "foo.txt", "w" );
fprintf( fh, "foo" );
When a user process starts, the kernel sets up three streams for the process, and (on POSIX) lists them as file descriptors 0 (stdin), 1 (stdout), and 2 (stderr) respectively.

That's why you see bash lines like:

Code: Select all

./xyz > log.txt 2> err.txt
These streams are by no means limited to keyboard and / or screen, it's just their default on most machines. (It isn't on embedded systems, for example.) If you start a process like this:

Code: Select all

./xyz > out.txt < in.txt
both stdin and stdout are actually files. What's more, a userspace application could use freopen() to "close" stdout / stdin and reattach them to completely different files from what you wrote on the command line.

What an OS has to implement is some way for keyboard input to be available to read(2) from, and some way to write(2) to screen.

Unix/POSIX, with its "everything is a file" philosophy, does the trick by providing e.g. the terminal as a file (/dev/pts/1).

The difference between stdout and stderr, by the way, is that stdout is buffered, stderr is not. And before you go ahead and implement generic stream buffering on the kernel side, be advised that this buffering is already being done by the C library in userspace. The kernel itself shouldn't buffer individual streams. Perhaps it should buffer writes to a device, but not on the individual stream level.

Perhaps I'll join your efforts with this page later, but right now those remarks above must suffice.

Re: Wrote a skeleton page with basic Std Input/Output Theory

Posted: Thu Aug 27, 2009 10:06 am
by Brendan
Hi,
Solar wrote:What an OS has to implement is some way for keyboard input to be available to read(2) from, and some way to write(2) to screen.
I'd go a step further here - the OS (kernel and drivers) don't necessarily have to implement these things. For example, it could be implemented in a POSIX compatibility library (where the OS itself uses something entirely different for user interaction).


Cheers,

Brendan

Re: Wrote a skeleton page with basic Std Input/Output Theory

Posted: Thu Aug 27, 2009 10:17 am
by gravaera
Hmm...thanks. Article edited to reflect changes. I implemented basic StdIO in my kernel yesterday, with a very basic API.

Such that:

Code: Select all

class stdBuff;
class stdOut : public stdBuff;
class stdIn : public stdBuff;
class stdErr : public stdBuff;

class localStdIO : public stdOut, stdIn, stdErr;
class win32StdIO : public stdOut, stdIn, stdErr;
class linuxStdIO : public stdOut, stdIn, stdErr;
Where the Kbd was writing directly to the active Application's StdIn buffer.

I had only really catered for Keyboard input as the StdIn, since that's how I had imagined it. I had originally planned to have File Handles and whatnot requested by an application handled by the Storage Manager.

I'll read up on the POSIX and C specifications for STDIO and do my best to straighten out that article.

Re: Wrote a skeleton page with basic Std Input/Output Theory

Posted: Fri Aug 28, 2009 1:13 am
by Solar
What you are doing there is input and output, allright, but it isn't what is meant by the terms "standard" input and "standard" output. See, stdin / stdout aren't classes of their own, they are merely instances of the class Stream (to translate the C terminology to C++, which you are apparently using).

Your hierachy simply "smells" wrong. How about:

Code: Select all

class Stream;

Stream stdin( /dev/keyboard, Stream::LINEBUFFERED );
Stream stdout( /dev/console, Stream::LINEBUFFERED );
Stream stderr( /dev/console, Stream::UNBUFFERED );
?


@ Brendan:

Of course you are right. But I tend to "keep it simple" in such foundation talks. Having your kernel provide what the userspace Standard C library demands is more or less the default, which - IMHO - you have to understand first, before trying something "exotic".

Re: Wrote a skeleton page with basic Std Input/Output Theory

Posted: Fri Aug 28, 2009 8:44 am
by gravaera
I'd been thinking of the Std In and Std Out for a program (on the OS side of it) as beinga buffer to the resource that the program requests. Such that:

If program X opens up, it has a defalut connection to three standard facilities the system provides: An interface for receiving input from the user, (default the keyboard), an interface for generating output messages to the user which is abstracted in the sense that the program only sends its output to the StdOut and doesn't have to worry about how the output becomes translated into a form usable by the system, and StdErr which is a link to a system that provides a link to an immediate reporting source.

In that vein, the OS only has to provide a buffer of sorts for the application to read from, and the corresponding device to write to, and provide an interface function (e.g readchar(), readline(), read(int length)) which would cause characters from that buffer to be steamed ot the app, and removed from the buffer.

So the actual API for StdIO was one connection (Three types, two of which simply mimic the Interface of either Windows or Linux(incomplete...barely started actually)), and it provided base functions (readStdIn(), writeStdOut(), writeStdErr()) for interacting with each of the StdIO facilities associated with the App.

My whole OS is like a large Compatibility layer, in design. I've designed it to be able to easily provide base classes for any kind of foreign API. I'm still working out the rough spots where C & C++ will have to interact, but so far I even see POSIX layers being implemented ontop of my design as being possible.

I was hoping I could contribute to the Wiki by recording what bits of design and theory and tricky things I found out while developing in C++, but my extensions and my own implementation specific designed probably aren't good for a generally educative article.

But in the end StdIO is important to OSDev, so the article should be appended.