Red de conocimiento informático - Material del sitio web - Cómo escribir correctamente un demonio de Linux

Cómo escribir correctamente un demonio de Linux

1. El proceso demonio, también comúnmente llamado proceso demonio, es un proceso de servicio en segundo plano en Linux. Es un proceso de larga duración, generalmente independiente del terminal controlador, que periódicamente realiza ciertas tareas o espera a que ocurran ciertos eventos. Si desea que un proceso sea inmune a los cambios realizados por el usuario, la terminal o cualquier otra cosa, debe convertirlo en un demonio.

2. Pasos para crear un proceso demonio

1) Cree un proceso hijo y salga del proceso padre

Después de eso, todo el trabajo se completará en el proceso hijo, y el usuario podrá ejecutar otros comandos en el terminal shell, separándolo oficialmente del terminal de control.

En Linux, el proceso padre saldrá antes que el proceso hijo, lo que hará que el proceso hijo se convierta en un proceso huérfano. Siempre que el sistema encuentre un proceso huérfano, el proceso 1 (init) lo adoptará automáticamente, de modo que. el proceso hijo original El proceso se convierte en un proceso hijo del proceso inicial.

2) Crear una nueva sesión en un proceso hijo

Grupo de procesos: es una colección de uno o más procesos. Un grupo de procesos se identifica de forma única mediante un ID de grupo de procesos. Además del número de proceso (PID), el ID del grupo de procesos es un atributo obligatorio del proceso. Cada grupo de procesos tiene un proceso líder cuyo número de proceso es igual a la ID del grupo de procesos, y la ID del grupo no se ve afectada por la salida del proceso líder.

Ciclo de sesión: Un ciclo de sesión es una colección de uno o más grupos de procesos. Normalmente, una sesión comienza cuando un usuario inicia sesión y finaliza cuando el usuario cierra sesión, y todos los procesos que se ejecutan para ese usuario durante este período pertenecen al período de sesión.

(1) pid_t setsid(void);

Si el proceso que llama no es el líder del grupo de procesos, setid() creará una nueva sesión. El proceso de llamada será el único proceso en el nuevo grupo de procesos y la nueva sesión.

La función setsid se utiliza para crear una nueva sesión y actuar como líder del grupo de sesión. Llamar a setsid tiene los siguientes tres efectos:

① Dejar que el proceso se deshaga del control de la sesión original

② Deje que el proceso se deshaga del control del grupo de procesos original

③ Deje que el proceso se deshaga de Resulta que el control del punto final de control

tiene los siguientes tres resultados:

(a) Se convierte en el proceso principal de la nueva sesión

(b) Se convierte en el grupo del nuevo grupo de proceso Proceso largo

(c) no tiene terminal de control.

Se ha sugerido que se vuelva a llamar a fork en este punto y que cause que finalice el proceso principal. El segundo proceso hijo seguirá ejecutándose como un demonio. Esto asegurará que el proceso del demonio no sea el proceso principal de la sesión.

La función setid puede hacer que un proceso sea completamente independiente y así libre del control de otros procesos.

Después de llamar exitosamente a la función setid(), el proceso se convertirá en el nuevo proceso líder de sesión y en el nuevo proceso líder de proceso, y se separará de la sesión iniciada y del grupo de procesos originales. Debido a que el proceso de sesión es exclusivo del terminal de control, el proceso también se desconecta del terminal de control. El proceso hijo puede formar un nuevo grupo de procesos por sí mismo, es decir, llamar a setpgrp() para separarse del grupo de procesos original y generar un nuevo grupo de procesos cuyo número de grupo de procesos sea el mismo que su número de proceso. De esta manera, cuando el proceso principal sale, no afectará la ejecución actual del proceso secundario.

3) Cambie el directorio actual al directorio raíz

El proceso hijo creado usando fork heredará el directorio de trabajo actual del proceso padre cuando el proceso esté activo, su directorio de trabajo; está ubicado El sistema de archivos no podrá desmontarse. La práctica común es usar "/" como directorio de trabajo actual del demonio, o puede usar chdir para usarlo como otro directorio, como /tmp.

4) Restablecer la máscara de permiso de archivo

Máscara de permiso de archivo significa enmascarar los bits correspondientes en los permisos del archivo. Por ejemplo, existe una máscara de permiso de archivo de 050, que enmascara los permisos de lectura y ejecución del propietario del grupo de archivos. máscara = máscara & ~050

Normalmente, la máscara de permiso del archivo se establece en 0, que es umask(0).

5) Cerrar el descriptor de archivo

El nuevo proceso hijo creado usando la función fork heredará el descriptor de archivo abierto del proceso padre.

Es posible que el demonio nunca lea ni escriba estos archivos abiertos, pero aun así consumen recursos del sistema y pueden hacer que el sistema de archivos en el que residen se vuelva imposible de montar.

Después del segundo paso anterior, el proceso demonio pierde contacto con el terminal de control al que pertenece. Por lo tanto, los caracteres ingresados ​​desde el terminal no pueden llegar al demonio y los caracteres generados por el demonio usando métodos convencionales (como printf) no se pueden mostrar en el terminal. Por lo tanto, los tres archivos con los descriptores de archivo 0, 1 y 2 (a menudo llamados archivos de entrada, salida y error) han perdido su valor y deben cerrarse.

for(i=0;i

close(i);

6) Procesamiento de salida del demonio

Cuando los usuarios necesitan detener la ejecución externa del demonio, generalmente usan el comando kill para detener el demonio. Por lo tanto, el demonio necesita estar codificado para manejar la señal emitida por kill para lograr una salida elegante del proceso.

señal(SIGTERM, sigterm_handler);

void sigterm_handler(int arg)

{

_running = 0;

}

7) Procesamiento de la señal SIGCHLD

No es necesario procesar la señal SIGCHLD. Sin embargo, para algunos procesos, especialmente los procesos del servidor, los procesos secundarios a menudo se generan para manejar las solicitudes cuando llegan. Si el proceso padre no espera a que finalice el proceso hijo, el proceso hijo se convertirá en un zombi y ocupará 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 Linux, simplemente configura la operación de la señal SIGCHLD en SIG_IGN.

signal(SIGCHLD,SIG_IGN);

De esta manera, el kernel no creará un proceso zombie cuando finalice el proceso hijo.