Page 1 of 1

How keyboard input is sent to userspace programs

Posted: Sun Mar 20, 2022 4:02 am
by yasar11732
Hi,

My kernel is in very early stages. I am currently working on kernel level memory allocator, with plans to implement kernel multithreading and running userspace programs.

While thinking about what comes next, I realized I don't have any idea how keyboard input supposed to be handled in multiprocessing kernel.

When there is only kernel running, I can listen for keyboard interrupts, read scancodes, put them in a buffer so I can use them when necessary.

But when there is multiple userspace applications running, am I supposed to duplicate keyboard input for each process? Or hand it out in a first come first serve basis? Or should I send keyboard input terminal emulators so they decide what to do with it? If so, from viewpoint of kernel, how is a terminal emulator is different then any other process, so kernel knows to send keyboard input to them? How does shells fit into this picture?

I am sorry if this question is very broad, I just don't know about this topic to ask specific questions.

I tried searching for this topic, but online articles only talk about interrupts and scancodes and keymaps.

Best Regards,

Re: How keyboard input is sent to userspace programs

Posted: Sun Mar 20, 2022 5:11 am
by nullplan
yasar11732 wrote:But when there is multiple userspace applications running, am I supposed to duplicate keyboard input for each process? Or hand it out in a first come first serve basis? Or should I send keyboard input terminal emulators so they decide what to do with it? If so, from viewpoint of kernel, how is a terminal emulator is different then any other process, so kernel knows to send keyboard input to them? How does shells fit into this picture?
So this is the point where you need to figure out how you want to present devices to userspace. The way I would do it is to present a device file, say, /dev/input/event0, for the keyboard. If that file is opened for reading, the driver is initialized (which includes clearing out the input buffer, if any), and then keystroke events are delivered to the application in a uniform fashion for all input devices. I would also just present a framebuffer device, say, /dev/fb0. Then the initial process can launch a terminal emulator that reads keyboard events from the former and renders characters onto the latter. And the kernel will just push events on everyone reading from the event file.

The terminal emulator, then, will create a pseudo-terminal, and send the keystrokes as escape sequences into the PTY and receive escape sequences back, which it will then somehow display on the framebuffer. How it does this is beyond me and the kernel actually doesn't have to care.

And the shell is spawned from the terminal emulator on the other side of the PTY. It never gets to receive the keystrokes, it only gets the escape sequences. It never has to care about keyboard layouts and stuff.

Re: How keyboard input is sent to userspace programs

Posted: Wed Mar 23, 2022 12:46 pm
by eekee
yasar11732 wrote:But when there is multiple userspace applications running, am I supposed to duplicate keyboard input for each process? Or hand it out in a first come first serve basis? Or should I send keyboard input terminal emulators so they decide what to do with it? If so, from viewpoint of kernel, how is a terminal emulator is different then any other process, so kernel knows to send keyboard input to them? How does shells fit into this picture?
If you duplicate it for each process, what happens when one process wants the user to enter a password? :) So you have to send it to only one process. If you have a GUI, the GUI receives all key input and must decide where to send it. That's a simple concept.

Terminals might seem simpler still, but job control creates hidden surprises. There is a simple system which may have worked with shells in the early days of Unix: the shell just stops reading when the child process is running, but this makes job control impossible. What happens if a background process starts reading from the terminal? If the process was started in the background and there's no job control, the shell may have simply redirected its input to come from a device which always gives an error or something. (It may be preferable to redirect it's input from /dev/null; I'm not sure.) But if there is job control, the process may have been started in the foreground with a normal input, been suspended, then been backgrounded, so how could its input be changed? All the jobs started from a given shell can read from the same TTY as the shell, so the TTY device must know which process is the right one to send input to; which is the foreground task. (The difference between TTY & PTY is irrelevant here.) Knowing which is the foreground task is also necessary to send signals. I don't know how a TTY device knows which is the foreground process; perhaps the shell tells it, or perhaps the shell tells the kernel as it manages job control, but ultimately you get a similar situation to a GUI: the device relaying keyboard input to processes must decide which process to send it to.

Re: How keyboard input is sent to userspace programs

Posted: Wed Mar 23, 2022 2:33 pm
by rdos
Both keyboard input and what is displayed on screen (GUI or console) needs to have an "input focus" concept. At least if multiple consoles are supported.

In my design, each process has it's own keyboard buffer, and the kernel keyboard driver will post keys to the keyboard buffer that has input focus. Waiting for keys and reading out keyboard events always use the current process keyboard buffer. Emulation of stdin use the current process keyboard buffer as well.