Hola que tal, ya tiene un rato que no me aparesco en estos foros asi que me decidí a leer algunos posts. En general me encontre con que muchos tienen problemas con algunos temas fuertes de C y C++, asi que me he propuesto a realizar tutoriales de algunos de estos temas como:
* Manejo de señales
* Sockets
* Manejo de memoria dinámica
* Uso de fork para la creación de procesos hijos
y algún otro tema que se me vaya ocurriendo.
Sin mas preambulos, a continuación les muestro la forma en que podemos utilizar las señales de UNIX en nuestros propios códigos. Espero les sea de ayuda.
En UNIX hay distintas señales correspondientes a diferentes eventos que ocurren en el sistema, por ejemplo, cuando estamos ejecutando algun proceso (programa) en primer plano y oprimimos la combinación CTRL + C, enviamos la señal SIGINT (señal de interrupción) al proceso en cuestion, y de este modo lo detenemos.
Estas señales pueden ser utilizadas en nuestro programas. Imaginemos que tenemos un programa que abre diversos archivos y trabaja con ellos dentro de un bucle infinito, bueno pues, ahora imaginemos que queremos detener ese programa pero como buenos programadores queremos que los archivos que abrimos en este programa se cierren antes de la finalización del proceso. Precisamente para este tipo de situaciones podemos utilizar señales como SIGINT, asi al momento de oprimir CTRL + C, podemos hacer que el programa no solo cierre, si no que ANTES cierre todos los archivos que tenia abiertos.
A continuacion agrego una lista con las distintas señales manejadas en UNIX, descritas en el estandar POSIX.1-1990.
Código:
Signal Value Action Comment
──────────────────────────────────────────────────────────────────────
SIGHUP 1 Term Hangup detected on controlling terminal
or death of controlling process
SIGINT 2 Term Interrupt from keyboard
SIGQUIT 3 Core Quit from keyboard
SIGILL 4 Core Illegal Instruction
SIGABRT 6 Core Abort signal from abort(3)
SIGFPE 8 Core Floating point exception
SIGKILL 9 Term Kill signal
SIGSEGV 11 Core Invalid memory reference
SIGPIPE 13 Term Broken pipe: write to pipe with no
readers
SIGALRM 14 Term Timer signal from alarm(2)
SIGTERM 15 Term Termination signal
SIGUSR1 30,10,16 Term User-defined signal 1
SIGUSR2 31,12,17 Term User-defined signal 2
SIGCHLD 20,17,18 Ign Child stopped or terminated
SIGCONT 19,18,25 Cont Continue if stopped
SIGSTOP 17,19,23 Stop Stop process
SIGTSTP 18,20,24 Stop Stop typed at tty
SIGTTIN 21,21,26 Stop tty input for background process
SIGTTOU 22,22,27 Stop tty output for background process
The signals SIGKILL and SIGSTOP cannot be caught, blocked, or ignored.
Antes de continuar con esto de las señales combiene explicar otro aspecto, los PIDs (Process ID).
En UNIX, todos los procesos (incluso los del sistema) tienen un identificador llamado PID. Este identificador es el número asignado por el sistema y podemos conocerlo mediante la funcion getpid(), para utilizar esta función debemos incluir las librerias <sys/types.h> y <unistd.h>.
Para poder modificar el comportamiento de las señales de UNIX es necesario utilizar la libreria <signal.h>. Dentro de esta libreria podemos encontrar la función "signal". Esta función recibe dos parametros, el primer parametro que recibe es la señal sobre la que tendra efecto (cabe mencionar que las señales no son mas que constantes enteras, asi que basta con saber el número de la señal o el nombre de la constante) y el segundo parametro es el apuntador a una función, en la cual se define el comportamiento nuevo de la señal o señales. Un ejemplo sencillo podría ser el siguiente.
Código c:
Ver original#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
void misAcciones(int sig);
int main(void){
signal(SIGINT, misAcciones);
while(1) sleep(1);
}
void misAcciones(int sig){
switch(sig){
case SIGINT:
printf("Saliendo del programa\n"); break;
}
}
La forma en que se deben declarar las funciones utilizadas para modificar el comportamiento de las señales esta mostrada en el ejemplo. Debe ser una función que no regrese dato alguno, y que reciba un único parámetro de tipo entero.
Tambien es importante que al llamar esta función sea de la siguiente forma
Código:
signal(SIGINT, misAcciones);
es decir, sin "ningun" parámetro y sin paréntesis. Ya que la función "signal" te pide un APUNTADOR a una función.
La función "signal" manda automáticamente como parametro la señal capturada a "misAcciones", en este caso la recibe en la variable "sig". Por lo que si la funcion recibida es "SIGINT" mostrará en pantalla el mensaje "Saliendo del programa" y ejecutara un exit(0).
Espero esto les de una buena idea de como manejar señales en sus programas, por último les pongo un programa que hize para mostrar el uso de señales y de la funcion fork. Si tienen dudas haganmelas saber. Salu2
Código c:
Ver original#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#define MAX_HIJOS 3
#define INTERVALO 5
void temp(int sig);
void misAcciones(int sig);
int hijo[MAX_HIJOS];
int main (void){
int ppid = 0;
int contador = 0;
int pidActual;
ppid = getpid();
printf("Padre -> %i\n", ppid
); for(contador = 0; contador < MAX_HIJOS ; contador++){
pidActual = fork();
if(pidActual < 0) return -1;
if(pidActual == 0){
switch(contador){
case 0:
signal(30, misAcciones);
printf("HIJO[0] -> %i\n", getpid
()); while(1) pause();
break;
case 1:
signal(10, misAcciones);
printf("HIJO[2] -> %i\n", getpid
()); while(1) pause();
break;
case 2:
signal(16, misAcciones);
printf("HIJO[3] -> %i\n", getpid
()); while(1) pause();
break;
}
}
hijo[contador] = pidActual;
}
if(signal(SIGALRM, temp) == SIG_ERR)
printf("No fue posible cambiar acción a SIGALRM\n");
alarm(INTERVALO);
while(1) pause();
}
void temp(int sig){
printf("Temp: Me llamo %i\n", getpid
()); kill(hijo[0], 30);
kill(hijo[1], 10);
kill(hijo[2], 16);
alarm(INTERVALO);
}
void misAcciones(int sig){
int i, j;
switch(sig){
case 30:
for(i = 0; i < 300000; i++);
printf("Me llamo %i, con la senial %i\n", getpid
(), sig
); break;
case 10:
printf("Me llamo %i, con la senial %i\n", getpid
(), sig
); break;
case 16:
for(i = 0; i < 100000; i++)
for(j = 0; j < 100000; j++);
printf("Me llamo %i, con la senial %i\n", getpid
(), sig
); break;
}
}