views:

42

answers:

1

When I press a keyboard's key on some GTK application under Linux, what happens exactly? How does a key get received (from which device), interpreted, passed to the program, and then handled?

+5  A: 

It's actually rather a complex process...


  1. The keyboard has a 2D matrix of key connections and its own microprocessor or gate array containing a microprocessor. It is constantly scanning the matrix to find out if any keys are pressed. (To save pins, the keys are not individually tested.) The keyboard micro speaks a protocol with the keyboard controller in your CPU and transmits a message indicating a keypress.
  2. The keyboard controller notes the code and interrupts the CPU.
  3. The keyboard driver receives an interrupt, reads the keycode out of a controller register, and places the keycode in a buffer that links the interrupt side of the kernel to the per-process threads. It marks the thread waiting for keyboard input as "runnable"
  4. This thread wakes up. It turns out, this is the X server. The X server reads the keycode from the kernel.
  5. The server will will check to see which window has keyboard focus. The window will be connected to one of various clients.
  6. The server sends an event to the client that displayed that specific window. (Note that to the server, every textbox and such is a "window", not just entire applications.)
  7. The event loop in the client is waiting for the next server event message. This connection could be via TCP or it could be a local Unix feature. It uses read(2) or a socket op to actually get the next event message.
  8. The low-level xlib routine passes the keypress up to higher level widgets, eventually getting to a GTK function of some kind.
  9. The GTK API element hands the character to your program.

I glossed over language mappings, console multiplexing, and a few other things...

Update: So, /dev/input/* and in fact all of the /dev/* things are things called block or character special files. The important thing is that they have no stored data in the filesystem, just a major and minor device number that serve to look up a driver in the kernel in a table. It's almost that simple. If you ls -l /dev/input you will see a major and minor device number instead of a file size. The major number identifies the device driver and the minor number is a sort of instance-number that is passed (within the kernel) as a parameter to the driver.

DigitalRoss
Wow, I'm amazed by the depth of your understanding on the flow. I'm still unclear on real device to `/dev/input/*` association though.
OTZ