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.
Wrote a skeleton page with basic Std Input/Output Theory
- gravaera
- Member
- Posts: 737
- Joined: Tue Jun 02, 2009 4:35 pm
- Location: Supporting the cause: Use \tabs to indent code. NOT \x20 spaces.
Wrote a skeleton page with basic Std Input/Output Theory
17:56 < sortie> Paging is called paging because you need to draw it on pages in your notebook to succeed at it.
Re: Wrote a skeleton page with basic Std Input/Output Theory
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:
and
and
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:
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:
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.
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" );
Code: Select all
fprintf( stdout, "foo" );
Code: Select all
FILE * fh = fopen( "foo.txt", "w" );
fprintf( fh, "foo" );
That's why you see bash lines like:
Code: Select all
./xyz > log.txt 2> err.txt
Code: Select all
./xyz > out.txt < in.txt
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.
Every good solution is obvious once you've found it.
Re: Wrote a skeleton page with basic Std Input/Output Theory
Hi,
Cheers,
Brendan
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).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.
Cheers,
Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
- gravaera
- Member
- Posts: 737
- Joined: Tue Jun 02, 2009 4:35 pm
- Location: Supporting the cause: Use \tabs to indent code. NOT \x20 spaces.
Re: Wrote a skeleton page with basic Std Input/Output Theory
Hmm...thanks. Article edited to reflect changes. I implemented basic StdIO in my kernel yesterday, with a very basic API.
Such that:
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.
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;
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.
17:56 < sortie> Paging is called paging because you need to draw it on pages in your notebook to succeed at it.
Re: Wrote a skeleton page with basic Std Input/Output Theory
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:
?
@ 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".
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".
Every good solution is obvious once you've found it.
- gravaera
- Member
- Posts: 737
- Joined: Tue Jun 02, 2009 4:35 pm
- Location: Supporting the cause: Use \tabs to indent code. NOT \x20 spaces.
Re: Wrote a skeleton page with basic Std Input/Output Theory
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.
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.
17:56 < sortie> Paging is called paging because you need to draw it on pages in your notebook to succeed at it.