programando en linux gestión de procesos y señales realizado por: kepa bengoetxea...
TRANSCRIPT
Referencias
Programación en Linux con ejemplos.-Kurt WallDescripción Funcional de los Sistemas Operativos.-Iñaki AlegriaUNIX.Programación Avanzada.-Manuel Márquez
Antes de empezar
Antes de empezar a programar en c, instalar: sudo apt-get install build-essential
Se instalarán los siguientes paquetes extras: dpkg-dev g++ g+
+-4.2 libc6-dev libstdc++6-4.2-dev libtimedate-perl linux-libc-
dev patch
Paquetes sugeridos: debian-keyring g++-multilib g++-4.2-
multilib gcc-4.2-doc libstdc++6-4.2-dbg glibc-doc manpages-
dev libstdc++6-4.2-doc diff-doc
Para instalar el man de los comandos de usuario del sistema POSIX: sudo apt-get install manpages-posix
Creación de procesos
Entorno de un proceso consiste en un conjunto de variables que se le pasan al proceso en el momento de su creación. El entorno esta formado por una tabla NOMBRE-VALOR que se incluye en la pila del proceso. Ejm:
PATH=/usr/bin/:/home/pepe/bin
HOME=/home/pepe
Servicios o llamadas a sistema que brinda UNIX para manipular y gestionar procesos.
Llamadas a Sistema Podemos agrupar los servicios en las siguientes categorías:
gestión de procesos:
Crear: fork Cambiar: familia exec (execl, execv, execle, execve,
execlp, execvp) Terminar: exit Esperar: wait,waitpid
identificación de proceso: getpid, getppid, getuid, geteuid, getgid, getegid
entorno de un proceso: las variables de entorno que se pasan a un proceso son accesibles a través de la variable externa environ y las funciones getenv y setenv
Gestión de Proceso:Crear un proceso: exec
Las llamadas a exec, son una familia de funciones con interfaz diferente pero funcionan de forma igual.
La funciones de tipo exec cargan un programa en la zona de memoria del proceso que las ejecuta, sobreescribiendo los segmentos del programa antiguo con los del nuevo.
El programa viejo es sustituido y nunca retornaremos a él.
Si exec devuelve el control al programa que la invoca, es porque no se ha ejecutado correctamente. Devolviendo -1.
Gestión de Proceso:Crear un proceso: exec
La declaración de la familia de funciones exec es la siguiente:
//l:lista de argumentos
int execl(char * path, char * arg0, ...,char * argn, (char *)0);
//v:vector de argumentos
int execv(char * path, char *argv[]);
//e:enviroment (variables de entorno)
int execle(char * path, char * arg0, .,char * argn, (char*)0, char * envp[]);
int execve(char * path, char * argv[], char * envp[]);
Gestión de Proceso:Crear un proceso: exec
La declaración de la familia de funciones exec es la siguiente:
//p:busca un fichero ejecutable si el nombre de fichero especificado no contiene un carácter de barra inclinada
int execlp (char * file, char * arg0, ..., char * argn,(char*)0);
int execvp (char * file, char * argv[])
char * file es un puntero que apunta a la ruta del programa que queremos ejecutar
char * argv[] es un array de punteros a char que contiene los parámetros que queremos pasar a dicho programa (como si lo hiciéramos desde la linea de comandos), siendo el primer parámetro el nombre del mismo programa, y el último NULL, con lo que decimos que no quedan más parámetros .
Gestión de Proceso:Crear un proceso: exec
Si el programa esta escrito en C: copy.c
int main(int argc, char * argv[])
Llamada: copy fic1 fic2
argc argv
3
f \01ci
f \02ci
c \0ypo
argv[0]=”copy”argv[1]=”fic1”argv[2]=”fic2”
Gestión de Proceso:Crear un proceso: exec
La declaración de la familia de funciones exec es la siguiente:
char * path es un puntero que apunta al path name (absoluto o relativo) de un fichero ejecutable
char * arg0, ...*argn son punteros a cadenas de caracteres y constituyen la lista de argumentos que se le pasa al nuevo programa.
(char *)0 es un puntero a NULL, indica final de argumentos.
char * envp[] es un puntero a un array de punteros a cadenas de caracteres que constituyen el entorno en el que se va ejecutar el nuevo programa. Termina con NULL.
Gestión de Proceso:Crear un proceso: exec
Exec en detalle:
Función de si aceptan rutas/nombre de fichero:
execl,execv,exele y execve: “/bin/ls” execlp,execvp:”ls” busca PATH sino tiene “/” en el nombre
Reciben los parámetros como:
una lista de argumentos separados por comas:
“/bin/cat”,”/etc/passwd”,”/etc/group”,NULL un vector: char *
argv[]={“/bin/cat”,”/etc/passwd”,”/etc/group”};
Gestión de Proceso:Crear un proceso: exec
Exec en detalle:
Entorno:
Execve y execle permiten crear un entorno especializado para el programa:
char *envp[]={”PATH=/bin:/usr/bin”,”USUARIO=Juan Perez”}
El resto recibe sus entornos de manera implícita a través de la variable environ, esta se puede manipular con las funciones que estan en <stdlib.h>:
int putenv(const char *string);
char *getenv(const char *name);
Gestión de Proceso:Crear un proceso: exec
Ejemplos:
execl(“/bin/cat”,“/bin/cat”,”/etc/passwd”,”/etc/group”,NULL);
char * argv[]={“/bin/cat”,”/etc/passwd”,”/etc/group”,NULL};
execv(“/bin/cat”,argv);
char *argv[] = { "ls", "-l", NULL };
char *envp[] = { "HOME=/home/euiti", "LOGNAME=euiti", NULL};
execve ("/bin/ls", argv, envp);
Gestión de Proceso:Crear un proceso: exec
#include <stdio.h>
#include <unistd.h> /*man fork,exec */
#include <sys/types.h> /*man 2 wait */
#include <sys/wait.h> /*man 2 wait */
int main() {
int pid,status;
pid=fork();
Gestión de Proceso:Crear un proceso: exec
if (pid == 0) { /* Proceso Hijo */
if (execl("esclavo","esclavo", "nombre", "-a", NULL) == -1) {
printf("Error al ejecutar execl\n");
exit(1);} }
else { /* Proceso Padre */
wait(&status);
printf("\nEl proceso hijo finalizo con el estado %d\n", status);
exit(0);}
}
Gestión de Proceso:Crear un proceso: exec
esclavo.c:
#include <stdio.h>
int main(int argc, char *argv[]) {
int i = 0;
for (i = 0; i < argc; i++) printf("\nArgumento [%d]: %s", i, argv[i]);
exit(0);}
gcc -o miexec.exe miexec.c
gcc -o esclavo esclavo.c
./miexec.exe
Gestión de Proceso:Crear un proceso: exec
./miexec.exe
Argumento [0]: esclavo
Argumento [1]: nombre
Argumento [2]: -a
El proceso hijo finalizo con el estado 0
Gestión de Proceso:Crear un proceso: fork
La uńica forma de crear un proceso en el sistema UNIX es mediante la llamada fork
El proceso que invoca se le llama proceso padre y el proceso creado es el hijo
fork crea un proceso hijo. El proceso hijo creado es una copia exacta del padre, excepto que recibe un valor diferente de la llamada fork. Devuelve 0 al proceso hijo y el PID del hijo al proceso padre y un valor -1 en caso de no poder crearse el proceso hijo.
Gestión de Proceso:Crear un proceso: fork
Cuando llamamos a fork, el kernel realiza las siguientes operaciones:
Busca una entrada libre en la tabla de procesos y la reserva para el proceso hijo
Asigna un identificador de proceso para el proceso hijo, es invariante mientras viva, es la clave para controlarlo.
Se crea un nuevo proceso hijo con sus propias copias del texto del programa,datos y segmentos de pila del padre, incluyendo UIDs y GIDs reales y efectivos, archivos abiertos y segmentos de memoria compartida (no hereda las alarmas programadas por alarm, ni las señales pendientes)
Retorna al proceso padre el PID del proceso hijo, y al proceso hijo le devuelve el valor de 0.
Gestión de Proceso:Crear un proceso: fork
El proceso padre, antes de finalizar se suspende hasta que el hijo
acaba, para evitar que éste se quede zombie. Para ello, utiliza la llamada al sistema wait(), que recibe en la variable status el estado en que el proceso hijo finalizó.
#include <stdio.h>
#include <unistd.h> /*man 2 fork */
#include <sys/types.h> /*man 2 wait */
#include <sys/wait.h>
int main() {
Gestión de Proceso:Crear un proceso: fork
Int pid = 0, status = 0;
if ((pid = fork()) == -1)
{ printf(''Error al crear proceso hijo\n'');exit(1); }
if (pid == 0)
{ printf(''El PID de mi padre es %d\n'',getppid()); exit(0); }
else
{ printf(''Mi PID es %d y el PID de mi hijo es %d\n'', getpid(), pid);
wait(&status);
printf(''\nEl proceso hijo finalizo con el estado %d\n'', status);
exit(0);}
Gestión de Proceso:Crear un proceso: fork
$gcc -o mifork.exe fork.c
$./mifork.exe
El PID de mi proceso padre es 4693
Mi PID es el 4693 y he creado un proceso hijo cuyo pid es 4694
El proceso hijo finalizo con el estado 0
ó
Mi PID es el 4693 y he creado un proceso hijo cuyo pid es 4694
El PID de mi proceso padre es 4693
El proceso hijo finalizo con el estado 0
Gestión de Proceso:Esperar: wait
Un proceso zombie es un proceso que ha completado su ejecución y a liberado todos los recursos, pero aún tiene una entrada en la tabla de procesos, permitiendo al proceso que le ha creado lea el estado de su salida. Al padre se le envía una señal SIGCHLD indicando que el proceso ha muerto; el manejador para esta señal será típicamente ejecutar la llamada al sistema wait, que lee el estado de salida y borra al zombie. El ID del proceso zombie y la entrada en la tabla de procesos pueden volver a usarse. Los zombies pueden ser identificados con ps por la presencia de una Z en la columna de estado.
Gestión de Proceso:Esperar: wait
En UNIX el kernel asigna a "init" cualquier proceso cuyo padre muera antes que hacer un wait, automáticamente. "init" simplemente hace "wait" esperando que alguno de sus hijos (heredados) muera. No tiene que preocuparse de saber cuales son. "init" simplemente hace un "wait", descarta la notificación y hace otro, en un bucle. Su única misión es "limpiar" los procesos zombie (zombie: proceso muerto a la espera de que su padre haga un wait)). A estos procesos se le llaman procesos huérfanos.
Gestión de Proceso:Esperar: wait
wait: La función wait suspende la ejecución del proceso actual hasta que un proceso hijo ha terminado, o hasta que se produce una señal cuya acción es terminar el proceso actual. Todos los recursos del sistema reservados por el hijo son liberados.
waitpid:Función que espera hasta que termine el proceso con pid
#include <sys/types.h> y #include <sys/wait.h>
pid_t wait(int *status)
pid_t waitpid(pid_t pid, int *status, int options);
Gestión de Proceso:Esperar: wait
Parámetros:
pid_t pid
Si -1: lo que significa que espera por cualquier proceso hijo; este es el mismo comportamiento que tiene wait.
Si 0: lo que significa que espera por cualquier proceso hijo cuyo ID es igual al del proceso llamante.
Si > 0: lo que significa que espera por el proceso hijo cuyo ID es igual al valor de pid.
Gestión de Proceso:Esperar: wait
Parámetros:
options:
WNOHANG (wait if no hang): que significa que vuelve inmediatamente si ningún hijo ha terminado.
WUNTRACED (wait if no traced) : que significa que también vuelve si hay hijos parados, y de cuyo estado no ha recibido notificación.
Ambas conductas: WNOHANG||WUNTRACED
Nínguna:0 (No vuelve, permanece a la espera)
variable entera ''status'' :el estado de salida del hijo (si el hijo ha acabado su ejecución sin error, lo normal es que devuelva cero)
Gestión de Proceso:Esperar: wait
Ejm:waitpid
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main() { int pid = 0, status = 0;
if ((pid = fork()) == -1){ printf("Error al crear proceso hijo\n");exit(1); }
if (pid == 0) { sleep(30);printf("El PID de mi padre es %d\n",getppid()); exit(0); }
Gestión de Proceso:Esperar: wait
Ejm:waitpid
else { waitpid(pid,&status,WNOHANG);
printf("Mi PID es %d y el PID de mi hijo es %d\n", getpid(), pid);
printf("\nEl proceso hijo finalizo con el estado %d\n", status);exit(0);}}
Al Ejecutar:
Mi PID es 17101 y el PID de mi hijo es 17102
El proceso hijo finalizo con el estado 0
$ El PID de mi padre es 1
Gestión de Proceso:Esperar: wait
Ejm: Si cambiamos por wait
else { wait(&status);
printf("Mi PID es %d y el PID de mi hijo es %d\n", getpid(), pid);
printf("\nEl proceso hijo finalizo con el estado %d\n", status);exit(0);}}
Al Ejecutar:
El PID de mi padre es 17270
Mi PID es 17270 y el PID de mi hijo es 17271
El proceso hijo finalizo con el estado 0
Gestión de Proceso:Identificación de proceso
Información del proceso:(Están en unistd.h)
getpid:Función que devuelve el identificador del proceso. Ejm:
pid_t getpid(void);
getppid:Función que devuelve el identificador del proceso padre. Ejm: pid_t getppid(void);
getuid:Función que devuelve el identificador de usuario real.Ejm:
uid_t getuid(void);
geteuid:Función que devuelve el identificador de usuario efectivo. Ejm:uid_t geteuid(void);
Gestión de Proceso:Identificación de proceso
getgid:Función que devuelve el identificador de grupo real. Ejm:
gid_t getgid(void);
getegid:Función que devuelve el identificador de grupo efectivo. Ejm:gid_t getegid(void);
Gestión de Proceso:Entorno de un proceso
Entorno de un proceso: las variables de entorno que se pasan a un proceso son accesibles a través de la variable externa environ (un array de apuntadores a char)
extern char **environ; ó extern char *environ[ ];
Obtener el valor de una variable de entorno:
#include <stdlib.h>
char * getenv (const char *name); Definir el entorno de un proceso:
#include <stdlib.h>
int putenv (const char *string);
Nota:extern: variable global y que está en otro fichero fuente.
Gestión de Proceso.Entorno de un proceso:environ
Es un programa que nos muestra el contenido de la variable environ, simula el script $env
#include <stdio.h>
int main(void)
{extern char **environ; /*char * environ[]
while (*environ)
puts(*environ++);
}
Nota:extern: variable global y que está en otro fichero fuente.
Gestión de Proceso.Entorno de un proceso:environ
$env y ./env.exe
TERM=xterm
SHELL=/bin/bash
HISTSIZE=1000
...
Gestión de Proceso:Entorno de un proceso:getenv y
setenv#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(void){
char variable_de_entorno[]={"MI_RUTA=/home/kepa/lana"};
if (putenv(variable_de_entorno))
puts("putenv fallo");
else
puts("putenv tuvo éxito");
Gestión de Proceso:Entorno de un proceso:getenv y
setenvif (getenv("MI_RUTA"))
printf("MI_RUTA=%s \n",getenv("MI_RUTA"));
else
puts("MI_RUTA sin asignar");
exit(EXIT_SUCCESS);}
$gcc entorno.c -o entorno.exe
$ ./entorno.exe
putenv tuvo exito
MI_RUTA=/home/kepa/lana
Gestión de Proceso:Terminar:
Un proceso puede terminar por:
Su función main llama a return
llama a exit de la librería estándar de C <stdlib.h> uso general
llama a _exit declarada en <unistd.h> llamada del sistema unix
llama a abort
es finalizado por una señal
Gestión de Proceso.Terminar:return
return:
return expresión;
Fuerza la salida inmediata de una función. Y provoca que se salte al punto en que se hizo la llamada a la función.
Si hay un valor asociado con return, se trata del valor de vuelta de la función.
Si el return es de la función del main() provoca el fin del programa.
Gestión de Proceso.Terminar:exit
exit: #include <stdlib.h>
void exit(int status);
La función exit produce la terminación normal del programa y la devolución de status al proceso padre. Antes de finalizar se llama a todas las funciones registradas con atexit() en orden inverso a su registro.
status es el valor que se le devuelve al proceso padre como estado de terminación del proceso, y se puede leer mediante una de las funciones de la familia de wait.
Nota: atexit - registra una función para ser llamada al momento de una terminación normal del programa.
Gestión de Proceso.Terminar:_exit
_exit: #include <unistd.h> void _exit(int status);
Termina inmediatamente la ejecución del proceso invocador
No se ejecutan las funciones que se encuentran registradas con atexit.
Gestión de Proceso:Abort
abort
#include <stdlib.h>: void abort(void);
La función abort() causa una terminación anormal y graba una imagen de la memoria. Todos los canales abiertos se cierran y borran. Genera la señal: SIGABRT
Uso: casos extremos Ejm: sin memoria
Gestión de Proceso:Enviar señal
abort
vi abortprueba.c
#include <stdio.h>
#include <stdlib.h>
int main(void)
{ abort();
/*el programa no debería llegar aqui*/
exit(EXIT_SUCCESS);}
Gestión de Proceso:Enviar señal
abort
$gcc -o abortprueba abortprueba.c
$./abortprueba
#permite el volcado de memoria del programa(core dump)
$ulimit -c unlimited
$./abortprueba
$ls -lias
core
¿En qué situaciones las usaremos?
Programación en Linux:
Cuando uno quiere o necesita utilizar las prestaciones de un programa externo en su própio código.(Ejm: ls)
Resulta vital recoger los código de salida del fork ó exec con wait. Y también que los programas llamen a return o exit antes de salir del programa para poder recoger sus códigos de salida.
En caso de que tengamos problemas de código podremos incluir abort para crear una imagen de un programa en ejecución escribirla en disco, para la depuración del mismo.
Gestión de Proceso:Enviar señal
kill:
#include <sys/types.h> y <signal.h>: int kill(pid_t pid, int sig);
Función que envía al proceso pid la señal SIGXXXX
devuelve 0 si ha ido bien y sino -1 si no se ha podido ejecutar.
Ejm:kill(pid,SIGTERM)
Gestión de Proceso:Enviar señal
kill: Función que envía al proceso pid la señal SIGXXXX
Su declaración esta en: #include <sys/types.h> y <signal.h>: int kill(pid_t pid, int sig);
Ejm:
#include <sys/types.h> /*kill y wait*/
#include <sys/wait.h> /*wait*/
#include <signal.h>/*kill*/
#include <stdlib.h>/*puts y exit*/
#include <stdio.h>/*printf*/
#include <unistd.h>/*fork*/
int main(void){
Gestión de Proceso:Enviar señal
kill:
pid_t hijo;
int condicion,valor_retornado;
if ((hijo=fork())==-1){perror("fork");exit(EXIT_FAILURE);}
if (hijo==0) {sleep(1000);exit(EXIT_SUCCESS);}
else {valor_retornado=kill(hijo,SIGKILL);
if (valor_retornado) {perror("kill");wait(&condicion);}
else {printf("%d eliminado\n",hijo);}
exit(EXIT_SUCCESS); }}
Gestión de Proceso:Enviar señal
kill:
$gcc -o killer killer.c
$ ./killer
6680 eliminado
Gestión de Proceso:Enviar señal
Señales
Suceso que tiene lugar en cualquier momento durante la ejcución de un proceso (Señal=Interrupción Software)
Cada señal tiene un nombre (kill -l ó man 7 signal) y las funciones que las tratan están en </usr/include/signal.h>
Cuando un proceso recibe una señal, este puede realizar :
Puede ignorar la señal Puede permitir que ocurra una acción predeterminada
normalmente un exit con/sin volcado de un fichero core. Puede capturar la señal, ejecutando una rutina de
tratamiento de señal(handler), y luego exit o volver a un estado anterior o al punto donde se produjo la interrupción.
Gestión de Proceso:Enviar señal
man 7 signal
signal - lista de las señales disponibles
Señal Valor Acción Comentario
----------------------------------------------------------------------
SIGHUP 1 A Cuelgue detectado en la terminal de
control o muerte del proceso de control
SIGINT 2 A Interrupción procedente del teclado(Crtl-C)(salida)
SIGQUIT 3 C Terminación procedente del teclado(Ctrl-4)(salida con core)
SIGILL 4 C Instrucción ilegal
Gestión de Proceso:Enviar señal
Señal Valor Acción Comentario
----------------------------------------------------------------------
SIGABRT 6 C Señal de aborto procedente de abort(3)
SIGFPE 8 C Excepción de coma flotante
SIGKILL 9 AEF Señal de matar
SIGSEGV 11 C Referencia inválida a memoria
SIGPIPE 13 A Tubería rota: escritura sin lectores
SIGALRM 14 A Señal de alarma de alarm(2)
SIGTERM 15 A Señal de terminación
Gestión de Proceso:Enviar señal
Señal Valor Acción Comentario
SIGUSR1 30,10,16 A Señal definida por usuario 1
SIGUSR2 31,12,17 A Señal definida por usuario 2
SIGCHLD 20,17,18 B Proceso hijo terminado o parado
SIGCONT 19,18,25 Continuar si estaba parado
SIGSTOP 17,19,23 DEF Parar proceso
SIGTSTP 18,20,24 D Parada escrita en la tty
SIGTTIN 21,21,26 D E. de la tty para un proc. de fondo
SIGTTOU 22,22,27 D S. a la tty para un proc. de fondo
Gestión de Proceso:Enviar señal
A-La acción por defecto es terminar el proceso
B-La acción por defecto es ignorar la señal
C-La acción por defecto es terminar el proceso y hace core dump
D-La acción por defecto es parar la ejecución del proceso
E-La señal no puede ser capturada por el programa(manipulada)
F-La señal no puede ser ignorada
*core dump: volcado de memoria del contexto del proceso a la
carpeta del proceso, para poder ver con un programa de
depuración como gdb,sdb o adb
Gestión de Proceso:Enviar señal.Pause
pause
Cuando queramos que un proceso espere a que llegue
una señal. Esta función provoca que el proceso
duerma hasta que llegue la señal.
Declaración: int pause (void)
Devuelve -1 cuando la llamada a la función que
captura la señal ha terminado.
Gestión de Proceso:Enviar señal.Pause
Ejm:vi pausa.c
#include <unistd.h>
#include <stdlib.h>
int main(void){pause();
exit(EXIT_SUCCESS);}
$gcc -o pausa pausa.c
$./pausa
Ctrl-4 ó kill -USR1 <PID>
Salir
Gestión de Proceso:Enviar señal.Signal
signal
man signal
La función signal() recibe dos parámetros, el número de señal que queremos capturar (los números en el sistema en concreto en el que nos encontremos los podemos obtener ejecutando “kill –l”, como ya hemos visto), y un puntero a una función que se encargará de tratar la señal especificada.También puede ser una de las siguientes macros: SIG_IGN (No tener en cuenta la señal) ó SIG_DFL( Dejar la señal con su comportamiento predefinido)
Signal devuelve SIG_ERR si ocurre un error.
Gestión de Proceso:Enviar señal
Conceptos básicos: Punteros a funciones.
Cuando una función en C se compila, se crea un punto de entrada en el código objeto.
Cuando se llama a la función se hace una llamada a ese punto de entrada.
El punto de entrada se puede utilizar para llamar a la función.
Declaración de puntero a función: tipo_devuelve_f (*p) ();
La dirección del punto de entrada se obtiene con el nombre de la fución sin paréntesis ni argumentos(Igual que los arrays)
Asignación: p=printf
Llamada: (*p)(“kaixo”)
Gestión de Proceso:Enviar señal
ejemplo
#include <stdio.h>
#include <signal.h>
int sig;
void funcion (sig)
{printf("Recibida la señal %d\n",sig);}
int main(){
/*Se habilita la función */
signal(SIGUSR1,funcion);
kill(getpid(),SIGUSR1);
/*Se ignora la señal*/
signal(SIGUSR1,SIG_IGN);
kill(getpid(),SIGUSR1);
/*Tratamiento por defecto*/
signal(SIGUSR1,SIG_DFL);
kill(getpid(),SIGUSR1);
return 0;
}
Gestión de Proceso:Enviar señal
alarm: Función que activa un temporizador en el proceso que efectúa la llamada. Cuando el tiempo asignado al temporizador expira, se envía SIGALRM al proceso que efectuo la llamada. Definida en <unistd.h>: unsigned int alarm(unsigned int seconds);
sleep:Función que hace que el proceso quede inactivo durante x segundos. Ejm: int sleep(unsigned int seconds);
Ejm:sleep(30)
Gestión de Proceso:Enviar señal.Alarm
Ejm:vi alarma.c
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
int main(void)
{ if ((alarm(5))>0) {puts("Ya hay una alarma programada");}
sleep(30);
puts("¿Como fue que el programa llego aqui?");
exit(EXIT_FAILURE);
}
Gestión de Proceso:Enviar señal.Alarm
$gcc -o alarma alarma.c
$ ./alarma
Reloj de alarma
Crear y Manipular señales
Programación en Linux:
El procedimiento general consiste en:
Crear un conjunto de señales Establecer las señales que se quieren interceptar Registrar un handler de señales en el kernel Aguardar a interceptar la señal
Utilizar las siguientes funciones del API que están en /usr/include/signal.h :sigemptyset,sigfillset,sigaddset...