Roger2

202 views
159 views

Published on

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
202
On SlideShare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
0
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Roger2

  1. 1. Servicios y demonios Código residente de ejecución con frecuencia programada para procesamiento de eventos
  2. 2. Programas residentes• Procesos que se arrancan y cuando finalizan dejan parte de su código instalado en memoria.• El código residente queda protegido por el sistema de administración de memoria del S.O.• El código resiente no se ejecuta por intervención directa del usuario.
  3. 3. Programas residentes• El código residente se ejecuta mediante señales de software o interrupciones de hardware.• Los programas AGENTES son rutinas residentes, diseñadas para Windows, tienen una interfaz GUI oculta y se registran en la barra de tareas del sistema.
  4. 4. Servicios• Programas residentes, sin interfaz gráfica, que son iniciados al arrancar el sistema.• No requieren que un usuario se registre para entrar en ejecución, siempre están activos.• Pueden ser configurados para arrancar en forma automática, manual o para ser deshabilitados.
  5. 5. Interfaz con el “Service Control Manager”• Se administran mediante la aplicación de servicios (“services”) dentro del Panel de Control/Herramienta.
  6. 6. Servicios• Los servicios pueden añadirse dinámicamente.• Los estados de un proceso son: – Habilitado – Deshabilitado – Iniciado – Iniciando – Detenido – Deteniéndose• Su inicio puede ser: – Manual – Automático
  7. 7. Servicios• Los servicios pueden activarse o desactivarse según se requiera, sin necesidad de reinicializar el sistema.
  8. 8. Para instalar un proceso se requiere ...Programa instalador. Da de alta el programa del proceso dentro de la base de servicios (procesos) de Windows.Programa del proceso. Contiene el código funcional del servicio (proceso).
  9. 9. Funciones relacionadas con servicios• CreateService• DeleteService• EnumServicesStatus• RegisterServiceCtrlHandler• SetServiceStatus• ServiceMain
  10. 10. Eventos que puede recibir/enviar un servicio• SERVICE_STOPPED• SERVICE_START_PENDING• SERVICE_STOP_PENDING• SERVICE_RUNNING• SERVICE_CONTINUE_PENDING• SERVICE_PAUSE_PENDING• SERVICE_PAUSED • SERVICE_ACCEPT_STOP • SERVICE_ACCEPT_PAUSE_CONTINUE • SERVICE_ACCEPT_SHUTDOWN
  11. 11. Ejemplo de un servicioSERVICE_STATUS_HANDLE manejador;SERVICE_STATUS serviceStatus;SERVICE_TABLE_ENTRY tabla;char nombreServicio[]="Srv_ProgAva";VOID WINAPI ServiceMain(DWORD dwArgc,LPTSTR *lpszArgv);VOID WINAPI mainHandle(DWORD fdwControl);void main(void){ tabla.lpServiceName=nombreServicio; tabla.lpServiceProc=&ServiceMain; StartServiceCtrlDispatcher(&tabla);} Declaración de las rutinas que servirán para las operaciones principales del servicio. Estas hay que indicarlas ya que sus nombres no son estándares de Windows, sino un capricho del programador.
  12. 12. Ejemplo de un servicioSERVICE_STATUS_HANDLE manejador;SERVICE_STATUS serviceStatus;SERVICE_TABLE_ENTRY tabla;char nombreServicio[]=“Srv_ProgAva";VOID WINAPI ServiceMain(DWORD dwArgc,LPTSTR *lpszArgv);VOID WINAPI mainHandle(DWORD fdwControl);void main(void){ tabla.lpServiceName=nombreServicio; tabla.lpServiceProc=&ServiceMain; StartServiceCtrlDispatcher(&tabla);} Declaración de la estructura de datos SERVICE_TABLE_ENTRY. Inicialización de la estructura.
  13. 13. Estructura SERVICE_TABLE_ENTRY“The SERVICE_TABLE_ENTRY structure is used by theStartServiceCtrlDispatcher function to specify the ServiceMainfunction for a Win32 service that can run in the calling process.” typedef struct _SERVICE_TABLE_ENTRY { LPTSTR lpServiceName; LPSERVICE_MAIN_FUNCTION lpServiceProc; } SERVICE_TABLE_ENTRY, *LPSERVICE_TABLE_ENTRY; “Members lpServiceName  Pointer to a null-terminated string that names a service that can run in this service process. This string is ignored if the service is installed in the service control manager database as a SERVICE_WIN32_OWN_PROCESS service type. For a SERVICE_WIN32_SHARE_PROCESS service process, this string names the service that uses the ServiceMain function pointed to by the lpServiceProc member.”
  14. 14. Ejemplo de un servicioSERVICE_STATUS_HANDLE manejador;SERVICE_STATUS serviceStatus;SERVICE_TABLE_ENTRY tabla;char nombreServicio[]="Srv_ProgAva";VOID WINAPI ServiceMain(DWORD dwArgc,LPTSTR *lpszArgv);VOID WINAPI mainHandle(DWORD fdwControl);void main(void){ tabla.lpServiceName=nombreServicio; tabla.lpServiceProc=&ServiceMain; StartServiceCtrlDispatcher(&tabla);} Declaración de las rutinas que servirán para las operaciones principales del servicio. Estas hay que indicarlas ya que sus nombres no son estándares de Windows, sino un capricho del programador.
  15. 15. Función StartServiceCtrlDispatcherThe StartServiceCtrlDispatcher function connects the main thread of a service process to the servicecontrol manager, which causes the thread to be the service control dispatcher thread for the callingprocess.BOOL StartServiceCtrlDispatcher( LPSERVICE_TABLE_ENTRY lpServiceStartTable // address of service // table); Parameters lpServiceStartTable Pointer to an array of SERVICE_TABLE_ENTRY structures containing one entry for each service that can execute in the calling process. The members of the last entry in the table must have NULL values to designate the end of the table. Return Values If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To get extended error information, call GetLastError. Errors The following error code can be set by the service control manager. Other error codes can be set by the registry functions that are called by the service control manager. Value Meaning ERROR_INVALID_DATA The specified dispatch table contains entries that are not in the proper format. ERROR_SERVICE_ALREADY_RUNNING Windows NT 5.0 and later: The process has already called StartServiceCtrlDispatcher. Each process can call StartServiceCtrlDispatcher only one time.
  16. 16. Rutina ServiceMainVOID WINAPI ServiceMain(DWORD dwArgc,LPTSTR *lpszArgv){ serviceStatus.dwServiceType=SERVICE_WIN32_OWN_PROCESS; serviceStatus.dwCurrentState=SERVICE_START_PENDING; //Avisar que ... // ESTAMOS INICIANDO serviceStatus.dwControlsAccepted=SERVICE_CONTROL_INTERROGATE// ...EL ARRANQUE! |SERVICE_ACCEPT_STOP |SERVICE_ACCEPT_PAUSE_CONTINUE |SERVICE_ACCEPT_SHUTDOWN; serviceStatus.dwWin32ExitCode=NO_ERROR; serviceStatus.dwServiceSpecificExitCode=0; serviceStatus.dwCheckPoint=estado++; serviceStatus.dwWaitHint=100; Inicialización de la estructura serviceStatus para interfaz_al_SCM=RegisterServiceCtrlHandler(nombreServicio,mainHandle); preparar el arranque del servicio. SetServiceStatus(interfaz_al_SCM,&serviceStatus); //Avisar que estamos
  17. 17. Rutina ServiceMainVOID WINAPI ServiceMain(DWORD dwArgc,LPTSTR *lpszArgv){ serviceStatus.dwServiceType=SERVICE_WIN32_OWN_PROCESS; serviceStatus.dwCurrentState=SERVICE_START_PENDING; //Avisar que ... // ESTAMOS INICIANDO serviceStatus.dwControlsAccepted=SERVICE_CONTROL_INTERROGATE// ...EL ARRANQUE! |SERVICE_ACCEPT_STOP |SERVICE_ACCEPT_PAUSE_CONTINUE |SERVICE_ACCEPT_SHUTDOWN; serviceStatus.dwWin32ExitCode=NO_ERROR; serviceStatus.dwServiceSpecificExitCode=0; serviceStatus.dwCheckPoint=estado++; serviceStatus.dwWaitHint=100; Registrar la rutina que de ahora en adelante servirá interfaz_al_SCM=RegisterServiceCtrlHandler(nombreServicio,mainHandle); para recibir mensajes del sistema operativo. SetServiceStatus(interfaz_al_SCM,&serviceStatus); //Avisar que estamos
  18. 18. Rutina ServiceMainVOID WINAPI ServiceMain(DWORD dwArgc,LPTSTR *lpszArgv){ serviceStatus.dwServiceType=SERVICE_WIN32_OWN_PROCESS; serviceStatus.dwCurrentState=SERVICE_START_PENDING; //Avisar que ... // ESTAMOS INICIANDO serviceStatus.dwControlsAccepted=SERVICE_CONTROL_INTERROGATE// ...EL ARRANQUE! |SERVICE_ACCEPT_STOP |SERVICE_ACCEPT_PAUSE_CONTINUE |SERVICE_ACCEPT_SHUTDOWN; serviceStatus.dwWin32ExitCode=NO_ERROR; serviceStatus.dwServiceSpecificExitCode=0; serviceStatus.dwCheckPoint=estado++; serviceStatus.dwWaitHint=100; Mandar la ServiceManager la indicación de que interfaz_al_SCM=RegisterServiceCtrlHandler(nombreServicio,mainHandle); nuestro servicio ya está activo. SetServiceStatus(interfaz_al_SCM,&serviceStatus); //Avisar que estamos
  19. 19. Rutina ServiceMainVOID WINAPI ServiceMain(DWORD dwArgc,LPTSTR *lpszArgv){ serviceStatus.dwServiceType=SERVICE_WIN32_OWN_PROCESS; serviceStatus.dwCurrentState=SERVICE_START_PENDING; //Avisar que ... // ESTAMOS INICIANDO serviceStatus.dwControlsAccepted=SERVICE_CONTROL_INTERROGATE// ...EL ARRANQUE! |SERVICE_ACCEPT_STOP |SERVICE_ACCEPT_PAUSE_CONTINUE |SERVICE_ACCEPT_SHUTDOWN; serviceStatus.dwWin32ExitCode=NO_ERROR; serviceStatus.dwServiceSpecificExitCode=0; serviceStatus.dwCheckPoint=estado++; serviceStatus.dwWaitHint=100; Llamar a nuestra rutina de inicialización ... mmmh, aunque esto debió haberse hecho antes del SetServiceStatus, interfaz_al_SCM=RegisterServiceCtrlHandler(nombreServicio,mainHandle); no? ... ¿por qué? SetServiceStatus(interfaz_al_SCM,&serviceStatus); //Avisar que estamos
  20. 20. Rutina mainHandleVOID WINAPI mainHandle(DWORD fdwControl){ switch(fdwControl) { case SERVICE_CONTROL_STOP: serviceStatus.dwServiceType=SERVICE_WIN32_OWN_PROCESS; serviceStatus.dwCurrentState=SERVICE_STOP_PENDING; serviceStatus.dwControlsAccepted=SERVICE_CONTROL_INTERROGATE |SERVICE_ACCEPT_STOP |SERVICE_ACCEPT_PAUSE_CONTINUE |SERVICE_ACCEPT_SHUTDOWN;... break; case SERVICE_CONTROL_PAUSE: serviceStatus.dwServiceType=SERVICE_WIN32_OWN_PROCESS; serviceStatus.dwCurrentState=SERVICE_PAUSE_PENDING; serviceStatus.dwControlsAccepted=SERVICE_CONTROL_INTERROGATE |SERVICE_ACCEPT_STOP |SERVICE_ACCEPT_PAUSE_CONTINUE |SERVICE_ACCEPT_SHUTDOWN;... break; case SERVICE_CONTROL_CONTINUE: serviceStatus.dwServiceType=SERVICE_WIN32_OWN_PROCESS; serviceStatus.dwCurrentState=SERVICE_CONTINUE_PENDING;... }} El servicio debe tener capacidad para responder a cada tipo de petición que pueda generar el
  21. 21. Rutina mainHandle....case SERVICE_CONTROL_CONTINUE: serviceStatus.dwServiceType=SERVICE_WIN32_OWN_PROCESS; serviceStatus.dwCurrentState=SERVICE_CONTINUE_PENDING; serviceStatus.dwControlsAccepted=SERVICE_CONTROL_INTERROGATE |SERVICE_ACCEPT_STOP |SERVICE_ACCEPT_PAUSE_CONTINUE |SERVICE_ACCEPT_SHUTDOWN; serviceStatus.dwWin32ExitCode=NO_ERROR; serviceStatus.dwServiceSpecificExitCode=0; serviceStatus.dwCheckPoint=estado++; serviceStatus.dwWaitHint=100; SetServiceStatus(interfaz_al_SCM,&serviceStatus); reactivarProceso(); serviceStatus.dwServiceType=SERVICE_WIN32_OWN_PROCESS; serviceStatus.dwCurrentState=SERVICE_RUNNING; serviceStatus.dwControlsAccepted=SERVICE_CONTROL_INTERROGATE |SERVICE_ACCEPT_STOP |SERVICE_ACCEPT_PAUSE_CONTINUE |SERVICE_ACCEPT_SHUTDOWN; serviceStatus.dwWin32ExitCode=NO_ERROR; serviceStatus.dwServiceSpecificExitCode=0; serviceStatus.dwCheckPoint=estado++; serviceStatus.dwWaitHint=100; SetServiceStatus(interfaz_al_SCM,serviceStatus); break;} Cada caso puede tener llamadas a diversas... rutinas, según corresponda para realizar
  22. 22. Instalador de un serviciochar nombreServicio[]=“Srv_ProgAva"; //Así lo reconocerá el S.O.char nombreDisplay[]=“Servicio_ProgAva"; //Así lo veremos en pantalla.char pathServicio[]=“C:ProgAvaservicio.exe"; //Aquí está el .exeSC_HANDLE manejadorServicios; //Descriptor del manejador de serviciosSC_HANDLE nuevoServicio; //Apuntador a nuestro nuevo servicioENUM_SERVICE_STATUS datos[200];int resume,bytesFaltantes,serviciosFaltantes,i;void main(void) { manejadorServicios=OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS); resume=0; for (i=0;i<20;i++) { resume=i; if (EnumServicesStatus(manejadorServicios,SERVICE_WIN32, SERVICE_STATE_ALL,&datos[0],sizeof(datos), &bytesFaltantes,&serviciosFaltantes,&resume)==NULL) { printf("(%d) Error!n",GetLastError()); else { printf("%d Servicio (Nombre) --> %sn",i,datos[i].lpServiceName); printf("%d Servicio (Display) -> %sn",i,datos[i].lpDisplayName); } }
  23. 23. Instalador de un serviciochar nombreServicio[]=“Srv_ProgAva"; //Así lo reconocerá el S.O.char nombreDisplay[]=“Servicio_ProgAva"; //Así lo veremos en pantalla.char pathServicio[]=“C:ProgAvaservicio.exe"; //Aquí está el .exeSC_HANDLE manejadorServicios; //Descriptor del manejador de serviciosSC_HANDLE nuevoServicio; //Apuntador a nuestro nuevo servicioENUM_SERVICE_STATUS datos[200];int resume,bytesFaltantes,serviciosFaltantes,i;void main(void) { manejadorServicios=OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS); resume=0; for (i=0;i<20;i++) { resume=i; if (EnumServicesStatus(manejadorServicios,SERVICE_WIN32, SERVICE_STATE_ALL,&datos[0],sizeof(datos), &bytesFaltantes,&serviciosFaltantes,&resume)==NULL) { printf("(%d) Error!n",GetLastError()); else { printf("%d Servicio (Nombre) --> %sn",i,datos[i].lpServiceName); printf("%d Servicio (Display) -> %sn",i,datos[i].lpDisplayName); } }
  24. 24. Instalador de un serviciochar nombreServicio[]=“Srv_ProgAva"; //Así lo reconocerá el S.O.char nombreDisplay[]=“Servicio_ProgAva"; //Así lo veremos en pantalla.char pathServicio[]=“C:ProgAvaservicio.exe"; //Aquí está el .exeSC_HANDLE manejadorServicios; //Descriptor del manejador de serviciosSC_HANDLE nuevoServicio; //Apuntador a nuestro nuevo servicioENUM_SERVICE_STATUS datos[200];int resume,bytesFaltantes,serviciosFaltantes,i;void main(void) { manejadorServicios=OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS); resume=0; for (i=0;i<20;i++) { resume=i; if (EnumServicesStatus(manejadorServicios,SERVICE_WIN32, SERVICE_STATE_ALL,&datos[0],sizeof(datos), &bytesFaltantes,&serviciosFaltantes,&resume)==NULL) { printf("(%d) Error!n",GetLastError()); else { printf("%d Servicio (Nombre) --> %sn",i,datos[i].lpServiceName); printf("%d Servicio (Display) -> %sn",i,datos[i].lpDisplayName); } }
  25. 25. Ejemplo del instalador de un serviciochar nombreServicio[]=“Srv_ProgAva";char nombreDisplay[]=“Servicio_ProgAva";char pathServicio[]="E:ProgAvaservicio.exe";SC_HANDLE manejadorServicios; //Descriptor del manejador de serviciosSC_HANDLE nuevoServicio; //Apuntador a nuestro nuevo servicioENUM_SERVICE_STATUS datos[200];int resume,bytesFaltantes,serviciosFaltantes,i;void main(void) { manejadorServicios=OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS); resume=0; for (i=0;i<20;i++) { resume=i; if (EnumServicesStatus(manejadorServicios,SERVICE_WIN32, SERVICE_STATE_ALL,&datos[0],sizeof(datos), &bytesFaltantes,&serviciosFaltantes,&resume)==NULL) { printf("(%d) Error!n",GetLastError()); else { printf("%d Servicio (Nombre) --> %sn",i,datos[i].lpServiceName); printf("%d Servicio (Display) -> %sn",i,datos[i].lpDisplayName); } }
  26. 26. Ejemplo del instalador de un serviciochar nombreServicio[]=“Srv_ProgAva";char nombreDisplay[]=“Servicio_ProgAva";char pathServicio[]="E:ProgAvaservicio.exe";SC_HANDLE manejadorServicios; //Descriptor del manejador de serviciosSC_HANDLE nuevoServicio; //Apuntador a nuestro nuevo servicioENUM_SERVICE_STATUS datos[200];int resume,bytesFaltantes,serviciosFaltantes,i;void main(void) { manejadorServicios=OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS); resume=0; for (i=0;i<20;i++) { resume=i; if (EnumServicesStatus(manejadorServicios,SERVICE_WIN32, SERVICE_STATE_ALL,&datos[0],sizeof(datos), &bytesFaltantes,&serviciosFaltantes,&resume)==NULL) { printf("(%d) Error!n",GetLastError()); else { printf("%d Servicio (Nombre) --> %sn",i,datos[i].lpServiceName); printf("%d Servicio (Display) -> %sn",i,datos[i].lpDisplayName); } }
  27. 27. Ejemplo del instalador de un serviciochar nombreServicio[]=“Srv_ProgAva";char nombreDisplay[]=“Servicio_ProgAva";char pathServicio[]="E:ProgAvaservicio.exe";SC_HANDLE manejadorServicios; //Descriptor del manejador de serviciosSC_HANDLE nuevoServicio; //Apuntador a nuestro nuevo servicioENUM_SERVICE_STATUS datos[200];int resume,bytesFaltantes,serviciosFaltantes,i;void main(void) { manejadorServicios=OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS); resume=0; for (i=0;i<20;i++) { resume=i; if (EnumServicesStatus(manejadorServicios,SERVICE_WIN32, SERVICE_STATE_ALL,&datos[0],sizeof(datos), &bytesFaltantes,&serviciosFaltantes,&resume)==NULL) { printf("(%d) Error!n",GetLastError()); else { printf("%d Servicio (Nombre) --> %sn",i,datos[i].lpServiceName); printf("%d Servicio (Display) -> %sn",i,datos[i].lpDisplayName); } }
  28. 28. Ejemplo del instalador de un servicio if((nuevoServicio=CreateService(manejadorServicios, nombreServicio,nombreDisplay,SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,pathServicio, NULL,NULL,NULL,NULL,NULL))==NULL) printf("(%d) Error al crear el servicio %sn", GetLastError(),nombreServicio); else printf("Servicio %s creado!!!n",nombreServicio); getchar();} //main
  29. 29. ‘¡¡¡Demonios!!!’ … “Linux Daemons”• Son procesos que se activan al iniciar la operación del “kernel” y finalizan cuando se apaga el sistema.• No requieren interacción con el usuario, por lo tanto son procesos que no tienen terminal de control y por eso se dice que se ejecutan en “background”.• Debido a lo anterior, el flujo de salida y de errores debe tratarse de manera particular.
  30. 30. Señales y demonios• Los procesos tipo “daemon” siguen un protocolo específico para interactuar con el “kernel” y con las aplicaciones que los requieren.• Las interfaces hacia un “daemon” pueden ser (entre otros): – Archivos. – “Pipes”. – “Sockets”. – Señales.• Su funcionamiento es similar al de un servicio en Windows, pero tienen una codificación distinta.
  31. 31. Señales de demonios• Las señales son eventos (interrupciones) de “software”.• Son útiles para procesar eventos asincrónicos (teclado, red, archivos, etc).• La definición de señales es particular de la implementación del sistema operativo, pero en el archivo <signal.h> se pueden encontrar las definiciones estándares.• Un programa define rutinas específicas para capturar señales, en él establece sus reglas de procesamiento; para esto se utiliza la directiva: void (*signal(int signo, void (*func)(int)))(int);
  32. 32. Señales• Al recibir una señal, un proceso puede hacer tres cosas: – Ignorar la señal. – Atrapar la señal y procesarla mediante su rutina de atención (“handler”); aunque se debe saber que hay señales que no se puede interceptar, tal como SIGKILL y SIGSTOP. – Pasar el evento al sistema operativo para que se realice su procesamiento de facto.• Para enviar una señal a un proceso se pueden utilizar un par de rutinas: int kill(pid_t pid, int signo); int raise(int signo);• Igualmente se puede enviar una señal desde una terminal utilizando el comando kill y conociendo en número de proceso.
  33. 33. “Signal handler”#include <stdio.h>#include <stdlib.h>#include <signal.h>static void signalHandler(int signo) { //El argumento es el número de la señal if (signo == SIGUSR1) printf("received SIGUSR1n"); else if (signo == SIGUSR2) printf("received SIGUSR2n"); else if (signo == SIGINT) printf("CTRL-C!!!n"); else if (signo == SIGQUIT) { printf("Bye, bye.n"); exit(0); } else if (signo == SIGKILL) printf("It will be not so easy to get rid of me!!!n"); else printf("received signal %dn", signo);}int main(void) {
  34. 34. Catálogo de señales Señal Acción de facto DescripciónSIGABRT “Terminate+core” Esta señal se genera al invocar la rutina abort(…) {<stdlib.h>}SIGALRM “Terminate” Es invocada cuando expira el tiempo establecido por la rutina alarm(…) {<unistd.h>. También está relacionada con la rutina setitimer(…).SIGCHLD “Ignore” Se genera en el proceso padre cuando un proceso hijo termina o se detiene.SIGCONT “Continue/ignore” Esta señal es útil para reactivar un proceso que ha sido detenido previamenteSIGHUP “Terminate” Esta señal se envía a un proceso en caso de detectarse que su terminar controladora se ha desconectado o cerrado.SIGINT “Terminate” Esta señal se genera al detectarse la pulsación de la combinación de teclas <Control-C>.SIGIO “Terminate/ignore” Se activa para indicar la detección de un evento asincrónico de E/ S.SIGKILL “Terminate” Es una de las que no es interceptable, siempre útil para brindar una forma segura para finalizar un proceso.SIGPIPE “Terminate” Esta señal marca un error en el mecanismo de comunicación entre procesos a través de “pipes”.
  35. 35. Catálogo de señales Señal Acción de facto DescripciónSIGQUIT “Terminate+core” Es similar a SIGINT, pero adicionalmente genera un archivo de depuración de errores (“core dump file”).SIGSTOP “Stop process” No puede ser interceptada ni ignorada, es la forma correcta de finalizar un proceso.SIGTERM “Terminate” Esta señal es generada por el comando “kill” de facto, sin parámetros adicionales.SIGURG “Ignore” Notificación de un evento urgente, como la llegada de datos a través de una interfaz de red.SIGUSR1 “Terminate” Su aplicación está definida por el programador/usuario.SIGUSR2 “Terminate” Su aplicación está definida por el programador/usuario.SIGVTALRM “Terminate” Esta señal se genera por la finalización de un contador virtual asociado con la función setitimer(…).SIGXCPU “Terminate+core” Esta señal se canaliza al proceso cuando él excede el uso de CPU que le ha sido establecido en el sistema.
  36. 36. Estructura de un demonio#include <stdio.h>#include <fcntl.h>#include <signal.h> Tres rutinas son esenciales:#include <unistd.h> • La rutina principal de inicialización general.rutina1 (…) { • Una rutina para inicializar el… funcionamiento del “daemon”} • La rutina para recibir señales y procesarlas en forma conveniente.rutina2 (…) {… Se pueden tener rutinas adicionales de}… soporte e invocaciones avoid signalHandler(int sigNum) { bibliotecas sin restricciones. switch(sigNum) { case SIGHUP: … break; case SIGTERM: … break;
  37. 37. daemonize()• Modificar la máscara de creación de archivos invocando a la rutina umask para evitar heredar dicha característica del proceso principal.• Clonar el proceso mediante un fork y hacer que el proceso padre finalice. Esto es útil para hacer simular al “shell” que el proceso ya terminó, desasociarlo de su terminal, de su usuario/grupo y renunciar a ser el proceso interactivo (“group leader”).• Invocar setsid para crear una nueva sesión de trabajo logrando tres cosas: convertirse en el proceso líder de la sesión, convertirse en el proceso líder de grupo y renunciar a tener una terminal controladora.• Cambiar el directorio de facto de trabajo al raíz, evitando así recibirlo heredado del padre.• Cerrar todos los descriptores de archivo que pudo haber heredado del proceso padre.• Asignar los descriptores de archivo 0, 1 y 2 a /dev/null (stdin, stdout, stderr).• Asegurarse de ser la única instancia del demonio activo.• Interceptar señales relevantes y canalizarlas a una rutina de atención.

×