Page 1 of 1
Getch(), timer_wait(), all that stuff.
Posted: Tue Jan 24, 2012 7:43 am
by zhiayang
Great. Not 6 hours after my previous thread, here I am again. Sorry...
Anyway, I have a question:
For functions like getch(), timer_wait, kbhit(), etc, how does one go about implementing them?
From what I find, using this:
Code: Select all
while(!got_ch)
{
//Do something
}
//Somewhere else
keyboard_handler(...)
{
got_ch = 1;
}
doesn't work. If I guessed correctly, (I don't have multitasking yet) the kernel gets stuck in the while loop, because the keyboard handler can't get called? Or do interrupts rip control (figuratively?) from the current function, then transfer control to the handler? If the former is true, does that mean I need multitasking to do stuff like waiting on a timer or keyboard press?
Else, if the latter is true, why doesn't my pseudocode work?
Re: Getch(), timer_wait(), all that stuff.
Posted: Tue Jan 24, 2012 7:55 am
by brain
get interrupt handling working and interrupt routines for the timer and keyboard before you attempt any of this.
Then it may be easier to do mulitasking first
Once youve got that working, consider this below:
Internally functions like getch() should be non-blocking, meaning if there is nothing to do they return an error code, instead of int getch() you'd want "int kgetch(int* character)", the return code indicating status, and if status is valid, setting the character in the pointer parameter.
This way you can poll the state of buffers etc without needing to block your process. This can be used as the lowest level building block on a blocking getch() provided to userland.
Of course if you wanted to be more advanced, events would be better but this certainly needs a more advanced system and i don't think youre quite there yet?
Let me know if this makes sense.
Re: Getch(), timer_wait(), all that stuff.
Posted: Tue Jan 24, 2012 7:58 am
by zhiayang
brain wrote:get interrupt handling working and interrupt routines for the timer and keyboard before you attempt any of this.
Then it may be easier to do mulitasking first
Once youve got that working, consider this below:
Internally functions like getch() should be non-blocking, meaning if there is nothing to do they return an error code, instead of int getch() you'd want "int getch(int* character)", the return code indicating status, and if status is valid, setting the character in the pointer parameter.
This way you can poll the state of buffers etc without needing to block your process.
Of course if you wanted to be more advanced, events would be better but this certainly needs a more advanced system and i don't think youre quite there yet?
Let me know if this makes sense.
Ah. But err... I'm at the memory management stage, I do have interrupt handling and all that.
So based on your advice, how would I wait for user input?
if I were to use
Code: Select all
while(!getch(*ptr))
{
//DO something
}
Wouldn't that have the same effect?
Re: Getch(), timer_wait(), all that stuff.
Posted: Tue Jan 24, 2012 7:58 am
by Brendan
Hi,
requimrar wrote:Anyway, I have a question:
For functions like getch(), timer_wait, kbhit(), etc, how does one go about implementing them?
The "getch()" and "kbhit()" functions look like they should be built on top of
some sort of IPC. Start by deciding how separate pieces of software (e.g. processes) should communicate with each other, then implement it, then design device driver interfaces to suit your IPC, then implement device drivers for things like keyboard, mouse, etc (that send data like characters and keypresses via. your IPC to whatever is listening at the other end).
The "timer_wait()" function looks like something that should be built into the scheduler - put some sort of reference to the task/thread onto some sort of queue, then tell the scheduler not to give the task/thread any CPU time. Then you'd have a timer IRQ that wakes tasks/threads up and tells the scheduler to give the "woken" tasks/threads CPU time again.
In general, there's an order to implement things. Normally it's (very roughly) something like "memory management, then scheduler, then IPC". If you start trying to mess about with device drivers, GUIs or applications before you've got the fundamental stuff done then you're wasting your time. It's like trying to build a house - you don't start with the roof, you start with the foundation.
Cheers,
Brendan
Re: Getch(), timer_wait(), all that stuff.
Posted: Tue Jan 24, 2012 8:03 am
by brain
no, you would need to actually implement the kgetch function.
Here is how i do it:
1) at the lowest level, the keyboard driver handles keypress interrupts, placing ascii codes into a buffer. The buffer has a read pointer and a write pointer, pressing keys increments the write ptr and reading keys increments the read ptr. The buffer is 'circular' and wraps round so long as the write ptr doesnt 'lap' the read ptr (which means buffer is full)
2) an internal kgetch function checks if there are characters in the buffer. If there are, it returns the tail item from the list, and removes it. If there are not it returns an error code.
3) in userland, a library calls kgetch, and uses this to build up a buffer if and when keys arrive. While the buffer is not complete (e.g. enter is not pressed) the process is 'blocked' meaning it is not run unless kgetch() returns non-error.
4) when kgetch() returns success AND an enter keypress, then the input is complete and the process stops calling kgetch(), the process ceased to be blocked and the input is complete.
In short you have to do all of this yourself... It takes a fair while to code it
Re: Getch(), timer_wait(), all that stuff.
Posted: Tue Jan 24, 2012 8:06 am
by zhiayang
brain wrote:no, you would need to actually implement the kgetch function.
Here is how i do it:
1) at the lowest level, the keyboard driver handles keypress interrupts, placing ascii codes into a buffer. The buffer has a read pointer and a write pointer, pressing keys increments the write ptr and reading keys increments the read ptr. The buffer is 'circular' and wraps round so long as the write ptr doesnt 'lap' the read ptr (which means buffer is full)
2) an internal kgetch function checks if there are characters in the buffer. If there are, it returns the tail item from the list, and removes it. If there are not it returns an error code.
3) in userland, a library calls kgetch, and uses this to build up a buffer if and when keys arrive. While the buffer is not complete (e.g. enter is not pressed) the process is 'blocked' meaning it is not run unless kgetch() returns non-error.
4) when kgetch() returns success AND an enter keypress, then the input is complete and the process stops calling kgetch(), the process ceased to be blocked and the input is complete.
In short you have to do all of this yourself... It takes a fair while to code it
Great, thanks.