what are the operations executed in kernel when cntrl+c is invoked .

Submitted by Anonymous
on April 4, 2008 - 3:25am

hi ,

what code gets executed in kernel when cntrl+c or cntrl+z is invoked while executing a program in command line.

controlling tty: ctrl+c ctrl+z

olecom
on
April 5, 2008 - 4:59pm

> what code gets executed in kernel when cntrl+c or cntrl+z
> is invoked while executing a program in command line.

I'm sure you can see that in sources. But i'll try to describe it generally, if you don't mind.

there is a notion of controlling terminal
http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap03.html#t...

so, if generating signals on "Certain input sequences" isn't switched off (man stty(1)), and terminal is controlling (e.g. not NO_CTTY, man open(2)), then kernel sends signals:

* ctrl+c (0x03)-- SIGINT (fixed)
* ctrl+z (0x1A)-- SIGSTOP

kernel code on ctrl-c or ctrl-z

mcmanus
on
April 5, 2008 - 3:06pm

Dear Anonymous,

This is a pretty crazy path - hopefully I can give you enough to go on. I'll just deal with ^C.. ^Z is similar.

The controlling tty processes each new character through n_tty_receive_char() in drivers/char/n_tty.c. If that keypress is the termios interrupt character (tested with INTR_CHAR()) then it proceeds to send SIGINT to the process group (assuming there is one) with kill_pgrp(). The interrupt character is ^C by default, but the application can change that if it likes with an ioctl() on the tty or preferably with glibc's tcsetattr().

At this point, the tty code is left behind and it is pretty much the same as if some other process had sent kill(SIGINT) to the code.

kill_pgrp() is in kernel/signal.c.. first it finds each process in the process group, and then calls group_send_sig_info() for each one. Nested in here is send_signal() which sticks the sigint information in a queue of the task's called shared pending.. then it wakes the process up (makes it ready to run) with the signal in the pending state.

I told you it was a twisty path. but we're making progress.

eventually the signalled process starts to run again, and off in architecture specific code (e.g. arch/x86/kernel/signal_32.c) do_notify_resume() is called. This code basically checks to see if, generically speaking, any signal handlers should be invoked instead of wherever the task last left off.

If it finds something it calls do_signal(), which gets the specific signal structure using get_signal_to_deliver() [back in the generic signal.c code] - which checks for blocked signals and all that kind of jazz.. and then actually sets up the new stack frame to run the SIGINT code on and all the ephemera involved in handling the return.

The path is a little different if you don't have a signal handler installed for SIGINT - the default behavior for that signal is simply to terminate. get_signal_to_deliver() checks for that directly and takes care of it inline without ever running the task again (possibly dumping core along the way).

hope this is helpful. kernel/signal.c is interesting reading.

--
Patrick McManus
Linux Consulting
http://www.ducksong.com/
http://bitsup.blogspot.com/

and path after actual key being pressed?

olecom
on
April 6, 2008 - 2:19pm

> This is a pretty crazy path - hopefully I can give you enough to go on. > I'll just deal with ^C.. ^Z is similar.
>
> The controlling tty processes each new character through
> n_tty_receive_char() in drivers/char/n_tty.c.

Before all this there are another crazy things in input (keyboard, usb alike or network), pseudo-TTY and console code. Terminal emulator is a byte checker and kernel signaling is a kind of, as you've said, kill()-like.

So, IMHO, describing all input parts will be more funny :) But it's kind of book chapter or something like that...
_______

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.