Aunque esta pregunta ha sido respondida, permítanme publicar un flujo detallado de eventos en el kernel de Linux.
Esto se copia completamente de las publicaciones de Linux: Señales de Linux: partes internas
en el blog "Publicaciones de Linux" en sklinuxblog.blogspot.in.
Programa Signal User Space C
Comencemos escribiendo un programa simple de espacio de usuario de señal C:
#include<signal.h>
#include<stdio.h>
/* Handler function */
void handler(int sig) {
printf("Receive signal: %u\n", sig);
};
int main(void) {
struct sigaction sig_a;
/* Initialize the signal handler structure */
sig_a.sa_handler = handler;
sigemptyset(&sig_a.sa_mask);
sig_a.sa_flags = 0;
/* Assign a new handler function to the SIGINT signal */
sigaction(SIGINT, &sig_a, NULL);
/* Block and wait until a signal arrives */
while (1) {
sigsuspend(&sig_a.sa_mask);
printf("loop\n");
}
return 0;
};
Este código asigna un nuevo controlador para la señal SIGINT. SIGINT puede enviarse al proceso en ejecución utilizando la combinación de teclas Ctrl+ C. Cuando se presiona Ctrl+ C, la señal asíncrona SIGINT se envía a la tarea. También es equivalente a enviar el kill -INT <pid>
comando en otra terminal.
Si haces un kill -l
(que es una minúscula L
, que significa "lista"), conocerás las diversas señales que se pueden enviar a un proceso en ejecución.
[root@linux ~]# kill -l
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP
6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR
31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3
38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8
43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7
58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2
63) SIGRTMAX-1 64) SIGRTMAX
También se puede usar la siguiente combinación de teclas para enviar señales particulares:
- Ctrl+ C- envía SIGINT qué acción predeterminada es finalizar la aplicación.
- Ctrl+ \ - envía SIGQUIT cuya acción predeterminada es terminar el núcleo de volcado de la aplicación.
- Ctrl+ Z- envía SIGSTOP que suspende el programa.
Si compila y ejecuta el programa C anterior, obtendrá el siguiente resultado:
[root@linux signal]# ./a.out
Receive signal: 2
loop
Receive signal: 2
loop
^CReceive signal: 2
loop
Incluso con Ctrl+ Co kill -2 <pid>
el proceso no terminará. En su lugar, ejecutará el controlador de señal y volverá.
Cómo se envía la señal al proceso
Si vemos el funcionamiento interno de la señal que se envía a un proceso y ponemos Jprobe con dump_stack en __send_signal
función, veremos el siguiente seguimiento de llamada:
May 5 16:18:37 linux kernel: dump_stack+0x19/0x1b
May 5 16:18:37 linux kernel: my_handler+0x29/0x30 (probe)
May 5 16:18:37 linux kernel: complete_signal+0x205/0x250
May 5 16:18:37 linux kernel: __send_signal+0x194/0x4b0
May 5 16:18:37 linux kernel: send_signal+0x3e/0x80
May 5 16:18:37 linux kernel: do_send_sig_info+0x52/0xa0
May 5 16:18:37 linux kernel: group_send_sig_info+0x46/0x50
May 5 16:18:37 linux kernel: __kill_pgrp_info+0x4d/0x80
May 5 16:18:37 linux kernel: kill_pgrp+0x35/0x50
May 5 16:18:37 linux kernel: n_tty_receive_char+0x42b/0xe30
May 5 16:18:37 linux kernel: ? ftrace_ops_list_func+0x106/0x120
May 5 16:18:37 linux kernel: n_tty_receive_buf+0x1ac/0x470
May 5 16:18:37 linux kernel: flush_to_ldisc+0x109/0x160
May 5 16:18:37 linux kernel: process_one_work+0x17b/0x460
May 5 16:18:37 linux kernel: worker_thread+0x11b/0x400
May 5 16:18:37 linux kernel: rescuer_thread+0x400/0x400
May 5 16:18:37 linux kernel: kthread+0xcf/0xe0
May 5 16:18:37 linux kernel: kthread_create_on_node+0x140/0x140
May 5 16:18:37 linux kernel: ret_from_fork+0x7c/0xb0
May 5 16:18:37 linux kernel: ? kthread_create_on_node+0x140/0x140
Entonces, la función principal para enviar la señal es la siguiente:
First shell send the Ctrl+C signal using n_tty_receive_char
n_tty_receive_char()
isig()
kill_pgrp()
__kill_pgrp_info()
group_send_sig_info() -- for each PID in group call this function
do_send_sig_info()
send_signal()
__send_signal() -- allocates a signal structure and add to task pending signals
complete_signal()
signal_wake_up()
signal_wake_up_state() -- sets TIF_SIGPENDING in the task_struct flags. Then it wake up the thread to which signal was delivered.
Ahora todo está configurado y se realizan los cambios necesarios en task_struct
el proceso.
Manejo de señal
La señal es verificada / manejada por un proceso cuando regresa de la llamada al sistema o si se realiza la devolución de la interrupción. La devolución de la llamada del sistema está presente en el archivo entry_64.S
.
Se llama a la función int_signal function desde la entry_64.S
cual se llama a la función do_notify_resume()
.
Verifiquemos la función do_notify_resume()
. Esta función verifica si tenemos la TIF_SIGPENDING
bandera establecida en task_struct
:
/* deal with pending signal delivery */
if (thread_info_flags & _TIF_SIGPENDING)
do_signal(regs);
do_signal calls handle_signal to call the signal specific handler
Signals are actually run in user mode in function:
__setup_rt_frame -- this sets up the instruction pointer to handler: regs->ip = (unsigned long) ksig->ka.sa.sa_handler;
SISTEMA llamadas y señales
Llamadas de sistema "lentas", por ejemplo, bloqueo de lectura / escritura, poner procesos en estado de espera:
TASK_INTERRUPTIBLE
o TASK_UNINTERRUPTIBLE
.
Una tarea en estado TASK_INTERRUPTIBLE
cambiará al TASK_RUNNING
estado mediante una señal. TASK_RUNNING
significa que se puede programar un proceso.
Si se ejecuta, su controlador de señal se ejecutará antes de completar la llamada al sistema "lenta". El syscall
no se completa por defecto.
Si se SA_RESTART
establece el indicador, syscall
se reinicia después de que finaliza el controlador de señal.
Referencias