Page 1 of 1
kprintf design choices
Posted: Fri Dec 24, 2004 2:50 am
by Colonel Kernel
This is a straightforward question about a very mundane topic...
Pretty much every kernel needs to have some equivalent of kprintf()... What I'm wondering is, how far do people go with the features and capabilities of their kprintf() equivalent? I'm thinking about two aspects in particular:
- How much of the width/alignment/etc. features of standard printf() do you implement in kprintf()?
- Do you put in enough flexibility that kprintf() can redirect its output to something like a serial port (e.g. -- to support remote kernel debugging), or is it strictly for dumping things to the screen?
Thanks in advance for participating in my boring survey.
Re:kprintf design choices
Posted: Fri Dec 24, 2004 6:55 am
by Mr. L
I tend to place three arugments on my kprintf equivalent function on the stack. 1st arg = colour attribute, 2nd arg = X position of text on screen and 3rd arg = y position of text on the screen. I always use the linear video ram memory address (0xB8000).
Re:kprintf design choices
Posted: Fri Dec 24, 2004 11:16 am
by Schol-R-LEA
To repeat a piece of advice that always seems to get disregarded, I would recommend decomposing this into two functions which kprintf() would call: ksprintf() for generating the formatted string, and kputs() to print it out (depending on how you do them, you may want a kputc() and/or a memcpy() as well). If nothing else, it would allow you to test the printing and the formatting seperately. You probably don't need to go to the extremes that Linux does (where the kprintf() function is mostly concerned with logging the message, determining it's priority, and sending the formatted string to a list of consoles of the priority level or lower), but at the same time there is no reason not to use good programming practices just because you are in the kernel - quite the opposite, in fact.
Re:kprintf design choices
Posted: Fri Dec 24, 2004 12:09 pm
by Colonel Kernel
Actually, I feel I've put too much generality and flexibility into my design. It feels overly complex to me, which is bad because I want this code to be rock-solid since it will be called mostly from my equivalent of panic().
Currently, I have several layers at work:
- KernelDisplay, which currently wraps VGA text-mode stuff. It handles wrapping, scrolling, font colour, etc.
- DisplayTextStream, which wraps KernelDisplay and implements an ITextStream interface. It deals with control characters (currently just tab and newline).
- TextWriter, which is similar in spirit to your ksprintf(). It deals with formatting, but does so via a set of type-specific function calls rather than through a printf-style format string. It sends its formatted output to anything that implements ITextStream, which could be either the KernelDisplay, or perhaps a remote kernel debugger in the future (I'm not even sure if this is a workable idea at this point... hence my original post). It also allows any object that implements ITextWritable to dump itself to the formatted output.
- KOut, a kprintf()-style utility that parses the format string and delegates to TextWriter as appropriate.
It's modular, but it feels like overkill to me... I'm trying to get a handle on the requirements of this kind of facility, in case I'll see an opportunity to simplify a bit.
I should also mention, I'm working on a microkernel -- I would assume this makes the requirements for formatted output somewhat "lighter"...
<edit>
Also, none of the stuff I've implemented so far uses dynamic memory allocation... because I haven't implemented that yet.
I'd like to avoid using it in this sub-system if possible -- again, because I want my panic() to depend on as little (and as robust) code as possible.
</edit>
Re:kprintf design choices
Posted: Sat Dec 25, 2004 12:17 am
by proxy
i actually have gone as far as to implement a pretty much complete libc in kernel land as I want anything i could even think to use to be available. so for my case my printf is entirely ansi compliant (short of printing floats).
I find this to be very nice since i can easily test code in user space then shove it into the kernel and see if it still works as i think it does.
proxy
Re:kprintf design choices
Posted: Sun Dec 26, 2004 2:46 pm
by Colonel Kernel
Schol-R-LEA wrote:
I would recommend decomposing this into two functions which kprintf() would call: ksprintf() for generating the formatted string, and kputs() to print it out (depending on how you do them, you may want a kputc() and/or a memcpy() as well).
I thought about it, and changed things around so that ITextStream accepts characters instead of entire strings, and buffers them before sending them to KernelDisplay. Sort of analagous to using kputc() instead of kputs(). This has simplified the logic a lot -- thanks for suggesting it!
The logic in KOut for parsing the % format specifiers is now a neat and tidy little table-driven state machine.
i actually have gone as far as to implement a pretty much complete libc in kernel land as I want anything i could even think to use to be available. so for my case my printf is entirely ansi compliant (short of printing floats).
Wow, that must have taken a lot of effort. I had enough trouble (i.e. -- too much complex logic) just getting this limited formatting syntax working:
Is your kernel a microkernel? If not, I could see why having the full functionality could be useful. If so, do you actually use many of these features?
For example, when considering whether to include support for '-' (left-align) and '*' (width specifier) in my kprintf()-equivalent, I thought about the number of places where I would actually need to print stuff in the microkernel. The big one that leapt to mind was the panic()-related things that dump register and stack contents to the screen. That would benefit from having padding/field width support. But then again, if that is the only major usage of it, could I not just hard-code enough spaces and tabs in the format string? It's a tradeoff and I'm having trouble deciding one way or the other -- keep the extra logic in the subsystem (more code that needs to be tested, but makes printing stuff easier) versus ditching the logic (less code to test that panic() depends on, but harder to get the formatting just right). Argh... It's the trival decisions that get me stuck the most.