谁在按 ctrl+c、tty 驱动程序或 shell 时将 SIGINT 发送到前台进程
who send SIGINT to foreground process when press ctrl+c, tty driver or shell
当我在登录 shell 执行命令时按 ctrl+c 时,前台进程被终止。
谁发出信号?
TTY 驱动程序是否直接向前台进程组发送 SIGINT?
或者 TTY 驱动程序是否将 SIGINT 发送到 shell 并且 shell 将信号重定向到前台进程组?
tty 驱动程序(特别是线路规程)会将信号直接发送到前台进程组。这是代码 from Linux,您可以在其中看到它只是获取前景组并向其发出信号:
/**
* [...]
* Called when a signal is being sent due to terminal input.
* [...]
*/
static void __isig(int sig, struct tty_struct *tty)
{
struct pid *tty_pgrp = tty_get_pgrp(tty);
if (tty_pgrp) {
kill_pgrp(tty_pgrp, sig, 1);
put_pid(tty_pgrp);
}
}
这是从同一文件中的输入处理函数调用的,其中 n_tty_receive_signal_char
距离调用 __isig
:
仅几步之遥
/**
* [...]
* Process an individual character of input received from the driver.
* This is serialized with respect to itself by the rules for the
* driver above.
* [...]
*/
static int
n_tty_receive_char_special(struct tty_struct *tty, unsigned char c)
{
struct n_tty_data *ldata = tty->disc_data;
/* [...] */
if (L_ISIG(tty)) {
if (c == INTR_CHAR(tty)) {
n_tty_receive_signal_char(tty, SIGINT, c);
return 0;
} else if (c == QUIT_CHAR(tty)) {
n_tty_receive_signal_char(tty, SIGQUIT, c);
return 0;
} else if (c == SUSP_CHAR(tty)) {
n_tty_receive_signal_char(tty, SIGTSTP, c);
return 0;
}
}
当我在登录 shell 执行命令时按 ctrl+c 时,前台进程被终止。
谁发出信号?
TTY 驱动程序是否直接向前台进程组发送 SIGINT?
或者 TTY 驱动程序是否将 SIGINT 发送到 shell 并且 shell 将信号重定向到前台进程组?
tty 驱动程序(特别是线路规程)会将信号直接发送到前台进程组。这是代码 from Linux,您可以在其中看到它只是获取前景组并向其发出信号:
/**
* [...]
* Called when a signal is being sent due to terminal input.
* [...]
*/
static void __isig(int sig, struct tty_struct *tty)
{
struct pid *tty_pgrp = tty_get_pgrp(tty);
if (tty_pgrp) {
kill_pgrp(tty_pgrp, sig, 1);
put_pid(tty_pgrp);
}
}
这是从同一文件中的输入处理函数调用的,其中 n_tty_receive_signal_char
距离调用 __isig
:
/**
* [...]
* Process an individual character of input received from the driver.
* This is serialized with respect to itself by the rules for the
* driver above.
* [...]
*/
static int
n_tty_receive_char_special(struct tty_struct *tty, unsigned char c)
{
struct n_tty_data *ldata = tty->disc_data;
/* [...] */
if (L_ISIG(tty)) {
if (c == INTR_CHAR(tty)) {
n_tty_receive_signal_char(tty, SIGINT, c);
return 0;
} else if (c == QUIT_CHAR(tty)) {
n_tty_receive_signal_char(tty, SIGQUIT, c);
return 0;
} else if (c == SUSP_CHAR(tty)) {
n_tty_receive_signal_char(tty, SIGTSTP, c);
return 0;
}
}