Red de conocimiento informático - Conocimiento informático - Cómo escribir un proceso demonio

Cómo escribir un proceso demonio

El proceso demonio es un proceso con una larga vida útil. Son independientes del terminal de control y periódicamente realizan determinadas tareas o esperan que se produzcan determinados eventos. Por lo general, comienzan cuando se inicia el sistema y finalizan cuando el sistema se apaga. Hay muchos procesos demonio en los sistemas Unix y la mayoría de los servidores se implementan mediante procesos demonio. Por ejemplo, cuando se inician los demonios del servicio de red inetd y del servicio web d, se puede iniciar el proceso de planificación del trabajo crond, y también pueden ser ejecutados por el terminal de usuario (generalmente un shell). En resumen, aparte de estas especialidades, los procesos demoníacos son básicamente los mismos que los procesos ordinarios. Por lo tanto, escribir un proceso de demonio es en realidad transformar un proceso ordinario en un proceso de demonio de acuerdo con las características del proceso de demonio mencionado anteriormente. Si todos tienen una comprensión más profunda de los procesos, será más fácil comprender y programar los procesos demonio.

Primero, echemos un vistazo a algunos procesos demonios del sistema comúnmente utilizados y veamos cómo se relacionan con varios conceptos: grupo de procesos, terminal de control y sesión. El comando p s imprime el estado de cada proceso en el sistema. Este comando tiene múltiples opciones; consulte el manual del sistema para obtener más detalles. Para ver la información requerida, ejecute: ps –axj

PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND

0 1 0 0 -1 S 0 0:04 init

p>

1 2 1 1 ? -1 SW 0 0:00 [keventd]

1 3 1 1 ? -1 SW 0 0:00 [kapm-idled]

0 4 1 1 ? -1 SWN 0 0:00 [ksoftirqd_CPU0]

0 5 1 1 ? -1 SW 0 0:00 [kreclaimd]

0 7 1 1 ? -1 SW 0 0 0:00 [bdflush]

0 8 1 1 ? 00 [kupdated]

1 9 1 1 ? -1 SWlt; 0 0:00 [mdrecoveryd]

1 17 1 1 ? /p>

1 92 1 1 ? -1 SW 0 0:00 [khubd]

1 573 573 573 ? p>1 578 578 578 ? -1 S 0 0:00 klogd -2

1 598 598 598 ? -1 S 32 0:00 mapa de puertos

El número de proceso es 1. Estos procesos de 2 son muy especiales y existen durante toda la vida del sistema. No tienen ID de proceso principal, ID de proceso de grupo ni ID de sesión. El demonio syslogd se puede utilizar en cualquier programa que registre mensajes del sistema para los operadores. Estos mensajes pueden imprimirse en una consola real o escribirse en un archivo. sendmail es el demonio de correo estándar. El programa de actualización escribe periódicamente el contenido de la caché del kernel en el disco duro (normalmente cada 30 segundos). Para hacer esto, el programa llama a la función sync(2) cada 30 segundos. El demonio cron ejecuta el comando especificado en la fecha y hora especificadas. Muchas tareas de gestión del sistema las implementa cron mediante la ejecución periódica de programas relacionados. El proceso inetd escucha la interfaz de red del sistema en busca de solicitudes entrantes a varios servidores de red. El demonio final, lpd, maneja las solicitudes de impresión individuales al sistema.

Tenga en cuenta que todos los demonios se ejecutan con los privilegios del superusuario (ID de usuario 0). Ninguno de los demonios tiene una terminal de control, el nombre de la terminal está establecido en un signo de interrogación (?) y el ID del grupo de proceso de primer plano de la terminal está establecido en -1. La falta de una terminal de control es el resultado de que el demonio llama a setsid. Todos los demonios, excepto los de actualización, son el primer proceso en el grupo de procesos y el primer proceso en la sesión, y son los únicos procesos en estos grupos de procesos y sesiones. Finalmente, cabe señalar que el proceso padre de todos estos demonios es el proceso de inicio.

Antes de entrar en la programación real, echemos un vistazo a los conceptos que debemos encontrar al escribir demonios: sesiones de combinación de procesos.

Grupo de procesos

Además de un ID de proceso, cada proceso también pertenece a un grupo de procesos (los grupos de procesos participarán cuando se analicen las señales. Un grupo de procesos es uno o más procesos). recopilación. Cada proceso tiene un ID de grupo de procesos único. El ID del grupo de procesos es similar al ID del proceso: es un número entero positivo y se puede almacenar en el tipo de datos pid_t.

Cada grupo de procesos tiene un proceso líder. La identidad del proceso líder del grupo es que su ID de grupo de procesos es igual a su ID de proceso. Siempre que haya un proceso en un grupo de procesos, puede crear procesos en el grupo y luego finalizarlo. En cierto grupo de procesos, el líder del grupo de procesos puede El proceso existe independientemente de si su proceso líder termina. El intervalo de tiempo desde la creación de un grupo de procesos hasta la salida del último proceso se denomina vida útil del grupo de procesos. El último proceso de un grupo de procesos puede terminar o unirse a otro grupo de procesos.

Como se mencionó anteriormente, un proceso que llama a setgid puede unirse a un grupo existente o crear un nuevo grupo de procesos (setsid también puede crear un nuevo grupo de procesos, que se usará más adelante)

Sesión Sesión

Una sesión es una colección de uno o más grupos de procesos. Entre ellos, hay tres grupos de procesos en una sesión y, por lo general, varios procesos se agrupan mediante una canalización de shell.

A continuación se describen algunas características sobre sesiones y grupos de procesos:

Una sesión puede tener un terminal de control separado (terminal de control), que generalmente es donde iniciamos sesión en el dispositivo terminal (inicio de sesión de terminal). ) o dispositivo pseudoterminal (inicio de sesión de red), pero este terminal de control no es necesario.

El primer proceso de la sesión que establece conexión con el terminal de control se denomina proceso controlador (proceso de control). Y varios grupos de procesos en una sesión se pueden dividir en un grupo de procesos en primer plano (grupo de procesos en primer plano) y uno o varios grupos de procesos en segundo plano (grupo de procesos en segundo plano)

Si una sesión tiene un terminal de control, entonces tiene un grupo de procesos en primer plano y otros grupos de procesos son grupos de procesos en segundo plano. Siempre que escriba la tecla de interrupción (generalmente eliminar o ctrl-c) o la tecla de salida (generalmente ctrl-/), hará que la señal de interrupción o la señal de salida se envíe a todos los procesos en el grupo de procesos futuro.

Reglas de programación para procesos demonio

En diferentes entornos Unix, los detalles de programación específicos de los procesos demonio no son consistentes. Pero, afortunadamente, los principios de programación del proceso demonio son en realidad los mismos. La única diferencia radica en los detalles de implementación específicos. Este principio es para cumplir con las características del proceso demonio. Las reglas de programación son las siguientes:

1. Ejecutar en segundo plano

Para evitar que el terminal de control se cuelgue, el demonio debe ponerse en segundo plano para su ejecución. llamar a fork en el proceso para hacer que el proceso padre finalice y dejar que el demonio se ejecute en segundo plano en el proceso hijo. Específicamente, se trata de llamar a fork y luego hacer que el proceso principal salga. Esto logra los siguientes puntos:

Primero, si el proceso elf se inicia mediante un simple comando de shell l, la terminación del proceso principal hace que shel l piense que el comando se ha completado.

En segundo lugar, el proceso hijo hereda el ID del grupo de procesos del proceso padre, pero tiene un nuevo ID de proceso, lo que garantiza que el proceso hijo no sea el primer proceso de un grupo de procesos. Este es un requisito previo necesario para que la llamada al set s id se realice a continuación.

2. Separado del terminal de control, la sesión de inicio de sesión y el grupo de procesos

La sesión de inicio de sesión puede contener múltiples grupos de procesos, y estos grupos de procesos generalmente comparten un terminal de control. El terminal de inicio de sesión, el terminal de control, la sesión de inicio de sesión y el grupo de procesos del proceso de creación generalmente se heredan del proceso principal. Nuestro propósito es deshacernos de ellos y no vernos afectados por ellos.

El método se basa en el primer punto, llamando a setsid() para convertir al proceso en líder de sesión:

Cabe señalar que cuando el proceso es líder de sesión, setsid ( ) La llamada fallará, pero el primer punto garantiza que el proceso no sea el líder de la sesión. Después de que la llamada a setsid() sea exitosa, el proceso se convierte en el nuevo líder del grupo de sesión y el nuevo líder del grupo de procesos, y se separa de la sesión de inicio de sesión y del grupo de procesos originales. Debido a la exclusividad del proceso de sesión en el terminal de control, el proceso. se separa del terminal de control al mismo tiempo.

La operación específica es:

(a) Convertirse en el primer proceso de una nueva sesión

(b) Convertirse en el primer proceso de un nuevo grupo de procesos

(c) No hay terminal de control.

3. Prohibir que el proceso vuelva a abrir la terminal de control

Ahora, el proceso se ha convertido en el líder de la sesión sin una terminal, pero puede volver a solicitar la apertura de una terminal de control. Puede evitar que un proceso vuelva a abrir la terminal de control haciendo que el proceso ya no sea el líder de la sesión:

4. Cerrar los descriptores de archivos abiertos

El proceso lo hereda del proceso principal que creó. eso Abrir descriptor de archivo. Si no se cierra, se desperdiciarán recursos del sistema, lo que provocará la imposibilidad de desmontar el sistema de archivos donde se encuentra el proceso y errores impredecibles. En términos generales, es necesario cerrar los tres descriptores de archivo 0, 1 y 2, es decir, entrada estándar, salida estándar y error estándar. Porque generalmente esperamos que el proceso del demonio tenga su propio sistema de entrada y salida de información, en lugar de enviar todo a la pantalla del terminal. Llame a fclose();

5. Cambie el directorio de trabajo actual

Cambie el directorio de trabajo actual al directorio raíz. El directorio de trabajo actual heredado del proceso principal puede estar en un sistema de archivos montado. Debido a que los procesos demonio generalmente existen hasta que el sistema se reinicia, si el directorio de trabajo actual del proceso demonio está en un sistema de archivos montado, el sistema de archivos no se puede desensamblar. Además, algunos procesos demonio pueden cambiar el directorio de trabajo actual a una ubicación específica y realizar su trabajo en esta ubicación. Por ejemplo, los procesos del demonio de cola de impresión de línea a menudo cambian sus directorios de trabajo a sus directorios de cola de impresión.

Puedes llamar a chdir ("directorio");

6. Restablecer la máscara de creación de archivos

Establece la máscara de creación del modo de archivo en 0. La creación de máscaras a partir de métodos de archivos heredados puede denegar la configuración de ciertos permisos. Por ejemplo, si el proceso del demonio quiere crear un archivo que el grupo pueda leer y escribir, y el método de archivo heredado crea una palabra de máscara que bloquea estos dos permisos, la legibilidad y escritura del grupo requerida no funcionará.

7. Procesamiento de la señal SIGCHLD

No es necesario procesar la señal SIGCHLD. Pero para algunos procesos, especialmente los procesos del servidor, a menudo generan procesos secundarios para solicitarlos cuando llega la solicitud. Si el proceso padre no espera a que finalice el proceso hijo, el proceso hijo se convertirá en un proceso zombie y seguirá ocupando recursos del sistema. Si el proceso principal espera a que finalice el proceso secundario, aumentará la carga sobre el proceso principal y afectará el rendimiento de concurrencia del proceso del servidor.

En el sistema V, puede simplemente configurar la operación de la señal SIGCHLD en SIG-IGN:

signal(SIGCHLD, SIG_IGN);

De esta manera, el kernel no generará una Señala cuando finaliza el proceso hijo. Esto es diferente de BSD4. En BSD4, debes esperar el final del proceso hijo antes de liberar el proceso zombie.

Instancia de proceso demonio

La instancia de proceso demonio consta de dos partes: el programa principal test.c y el programa de inicialización init.c. El programa principal informa el estado de ejecución al registro test.log en el directorio /tmp cada minuto. La función init_daemon en el programa de inicialización es responsable de generar el proceso demonio

void make_daemon(void)

{

pid_t pid;

ARCHIVO * lockfd ;

sigset_t sighup;

int i;

pid_t externo getsid(pid_t);

pid = fork( ); // Se genera el primer proceso hijo

if (pid lt; 0) {

printinfo("fork error!", INFOERROR);

exit(FAILEXIT) ;

}else if (pid gt; 0) {

printinfo("fork 1 ok! ", INFOSCREEN);

salir( OKEXIT);/ /Salir del proceso padre y deshacerse del control del shell

}

pid = getpid() //Obtener la identificación del proceso hijo en sí

lockfd = fopen(PIDFILE , "w"); // Lo siguiente es escribir el pid en el archivo

if (lockfd != NULL) {

fprintf(lockfd, "d/n", pid);

fclose(lockfd);

}//Escribir pid

if (getsid(0) ) != pid) {//Crear una nueva sesión

if (setsid() lt; 0) {

printinfo("backupdaemon setsid error!", INFOERROR

perror("setsid");

}

}

if(pid=fork()){//Generar el proceso hijo de nuevo, esta vez es el proceso nieto

exit(0);//Salir del proceso de generación anterior

}else if(pidlt;0){

exit(1);

}

close(1); //Cerrar el archivo

close(2);

chdir(rundir); //Cambiar el directorio de ejecución

umask(022); //Cambiar los permisos del archivo

}

El proceso del demonio de salida de errores no lo hace. pertenecen a cualquier terminal, por lo que cuando necesita generar cierta información, no puede. La información se envía directamente a la salida estándar y a la salida de error estándar como un programa normal. La mayoría de las veces no queremos que cada demonio escriba su propio mensaje de error en un archivo separado. Porque para los administradores de sistemas, será un dolor de cabeza recordar qué proceso demonio escribe en qué archivo de registro y verificar estos archivos con regularidad. Por lo tanto, necesitamos tener un mecanismo centralizado de registro de errores del demonio.

En la actualidad, muchos sistemas han introducido el proceso de grabación syslog para lograr este propósito. Dado que BSD syslog fue desarrollado y ampliamente utilizado en Berkeley, la mayoría de los procesos demonio utilizan el mecanismo BSD syslog. A continuación presentamos el uso de BSD syslog. Hay tres formas de generar mensajes de registro:

1 Las rutinas del kernel pueden llamar a la función de registro. Cualquier proceso de usuario puede leer estos mensajes abriendo y leyendo el dispositivo /dev/klog. Como no pretendemos escribir rutinas en el kernel, esta función no se describirá más.

2 La mayoría de los procesos de usuario (procesos demonio) llaman a la función syslog para generar mensajes de registro. Explicaremos su secuencia de llamadas a continuación. Esto hace que los mensajes se envíen al socket de datagrama del dominio Unix /dev/log.

3 Un proceso de usuario en este host, o en algún otro host conectado a este host a través de una red TCP/IP, puede enviar mensajes de registro al puerto UDP 514. Nota: Las funciones syslog no generan estos datagramas UDP; requieren una programación de red explícita por parte del proceso que genera los mensajes registrados. Normalmente, el demonio syslog lee los mensajes registrados en tres formatos. Este demonio lee un archivo de configuración al inicio. Generalmente, su nombre de archivo es /etc/syslog.conf, que determina dónde se deben enviar los diferentes tipos de mensajes. Por ejemplo, los mensajes de emergencia se pueden enviar al administrador del sistema (si está conectado) y mostrarse en la consola, mientras que los mensajes de advertencia se pueden registrar en un archivo. Este mecanismo proporciona la función syslog y su formato de llamada es el siguiente

#include

void openlog (char*ident, int option, int facility);

void syslog (int prioridad, char*format,...)

void closelog();

Llamar a openlog es opcional. Si no se llama a openlog, se llama automáticamente a openlog la primera vez que se llama a syslog. Llamar a closelog también es opcional y simplemente cierra el descriptor utilizado para comunicarse con el demonio syslog. Llamar a openlog nos permite especificar una identificación que se agregará a cada mensaje registrado. ident es generalmente el nombre del programa (por ejemplo, cron, inetd, etc.). La opción tiene 4 posibilidades: LOG_CONS Si el mensaje de registro no se puede enviar a syslog a través del datagrama de dominio Unix, el mensaje se escribe en la consola. LOG_NDELAY1 Abre inmediatamente el socket de datagrama del dominio Unix al demonio syslog sin esperar a que se registre el primer mensaje. Normalmente, el socket no se abre hasta que se registra el primer mensaje. LOG_PERROR Además de enviar mensajes de registro a syslog, también los envía a error estándar. Esta opción sólo es compatible con 4.3BSDReno y versiones posteriores. LOG_PID Cada mensaje contiene el ID del proceso. Esta opción puede ser utilizada por demonios que bifurcan un proceso hijo para cada solicitud. El propósito de configurar el parámetro de instalación en openlog es permitir que el archivo de configuración explique que los mensajes de diferentes instalaciones se procesan de diferentes maneras. Si no se llama a openlog, o se llama con una facilidad igual a 0, la facilidad se puede especificar como parte del parámetro de prioridad al llamar a syslog. Llamar a syslog produce un mensaje registrado. Su parámetro de prioridad es una combinación de instalación y nivel, y sus valores opcionales se enumeran a continuación. Los valores de nivel están ordenados de mayor a menor por prioridad