Red de conocimiento informático - Conocimiento informático - ¿Cómo escribir un programa en segundo plano de Linux Daemon?

¿Cómo escribir un programa en segundo plano de Linux Daemon?

Daemon es un proceso especial que se ejecuta en segundo plano. Es independiente del terminal de control y periódicamente realiza alguna tarea o espera que ocurra algún evento. Daemon es un proceso muy útil. La mayoría de los servidores Linux se implementan mediante procesos demonio. Por ejemplo, servidor de Internet inetd, servidor web httpd, etc. Al mismo tiempo, el proceso del demonio completa muchas tareas del sistema. Por ejemplo, el proceso de planificación del trabajo crond, el proceso de impresión lpd, etc.

La programación del demonio en sí no es complicada. Lo que sí es complicado es que los mecanismos de implementación de varias versiones de Unix son diferentes, lo que da como resultado reglas de programación inconsistentes para demonios en diferentes entornos Unix. Esto requiere que los lectores tengan en cuenta que pueden ocurrir errores al copiar las reglas de ciertos libros (especialmente BSD4.3 y versiones inferiores de System V) a Linux. A continuación se presentarán de manera integral los puntos clave de la programación de demonios en Linux y se brindarán ejemplos detallados.

1. Proceso demonio y sus características

La característica más importante del proceso demonio es que se ejecuta en segundo plano. En este punto, el programa de memoria residente TSR en DOS es similar. En segundo lugar, el demonio debe estar aislado del entorno en el que se ejecuta. Estos entornos incluyen descriptores de archivos abiertos, terminales de control, grupos de sesiones y procesos, directorios de trabajo y máscaras de creación de archivos. Estos entornos suelen ser heredados por el proceso demonio del proceso padre (especialmente el shell) que lo ejecuta. Finalmente, hay algo especial en la forma en que se inicia el demonio. Se puede iniciar desde el script de inicio /etc/rc.d cuando se inicia el sistema Linux, se puede iniciar mediante el proceso de planificación del trabajo crond y también se puede ejecutar mediante el terminal de usuario (generalmente un shell).

En resumen, aparte de estas características especiales, básicamente no hay diferencia entre los procesos demoníacos y 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 los lectores tienen una comprensión más profunda del proceso, será más fácil de entender y programar.

2. Puntos clave de la programación de demonios

Como se mencionó anteriormente, las reglas de programación para demonios en diferentes entornos Unix no son consistentes. Afortunadamente, los principios de programación de los procesos demonios son en realidad los mismos. La diferencia radica en los detalles de implementación específicos. Este principio es para cumplir con las características del proceso demonio. Al mismo tiempo, Linux se basa en SVR4 de Syetem V y sigue el estándar Posix, que es más conveniente de implementar que BSD4. Los puntos clave de la programación son los siguientes;

1. Ejecutar en segundo plano.

Para evitar colgar el terminal de control, coloque Daemon en segundo plano para su ejecución. El método consiste en llamar a fork en el proceso para finalizar el proceso principal y permitir que Daemon se ejecute en segundo plano en el proceso secundario.

if(pid=fork())

exit(0); //Es el proceso padre, finaliza el proceso padre y el proceso hijo continúa

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

Primero es necesario introducir la relación entre el proceso y el terminal de control, la sesión de inicio de sesión y el grupo de procesos en Linux: un proceso pertenece a un grupo de procesos. y el número de grupo de proceso (GID) es el ID de proceso (PID) del líder del proceso. Una sesión de inicio de sesión puede contener varios grupos de procesos. Estos grupos de procesos comparten una terminal de control. Esta terminal de control suele ser la terminal de inicio de sesión donde se creó el proceso.

El control de terminales, sesiones de inicio de sesión y grupos de procesos generalmente se heredan del proceso principal. Nuestro propósito es deshacernos de ellos y no vernos afectados por ellos. El método consiste en llamar a setsid() sobre la base del punto 1 para convertir al proceso en el líder de la sesión:

setsid()

Explicación: cuando el proceso es el líder de la sesión, La llamada a setsid() falló. Pero el primer punto ya asegura que el proceso no es 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 con el terminal de control, el proceso se desconecta del terminal de control al mismo tiempo.

3. Deshabilite el proceso para que no vuelva a abrir la terminal de control.

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

if(pid=fork())

exit(0); primer proceso hijo, el segundo proceso hijo continúa (el segundo proceso hijo ya no es el líder de la sesión)

4. Cerrar el descriptor de archivo abierto

El proceso comienza desde el proceso padre que Lo creó. Los descriptores de archivos abiertos se heredan. Si no se cierra, se desperdiciarán recursos del sistema, el sistema de archivos donde se encuentra el proceso no se podrá desmontar y se producirán errores impredecibles. Ciérrelos de la siguiente manera:

for(i=0; i cierra el descriptor de archivo abierto close(i); gt;

for(i=0; ilt; NOFILE; i)

5. Cambiar el directorio de trabajo actual

Cuando el proceso está activo, el sistema de archivos donde se encuentra el directorio de trabajo no se puede desmontar. Generalmente, es necesario cambiar el directorio de trabajo. el directorio raíz. Núcleo de almacenamiento, el proceso que escribe el registro de ejecución cambia el directorio de trabajo a un directorio específico como /tmpchdir("/")

6. p>El proceso lo crea desde El proceso padre hereda la máscara de creación de archivos. Puede modificar los bits de acceso de los archivos creados por el demonio. Para evitar esto, borre la máscara de creación de archivos: umask(0). >7. Manejar la señal SIGCHLD

No es necesario manejar la señal SIGCHLD, pero para algunos procesos, especialmente el proceso del servidor, a menudo se genera un proceso hijo para manejar la solicitud cuando llega la solicitud. El proceso no espera a que finalice el proceso hijo, el proceso hijo se procesará. Se convertirá en un proceso zombie y ocupará recursos del sistema. Si el proceso padre espera el final del proceso hijo, aumentará la carga para el padre. procesar y afectar el rendimiento de concurrencia del proceso del servidor En Linux, simplemente puede configurar la operación de señal SIGCHLD en SIG_IGN. /p>

signal(SIGCHLD, SIG_IGN); El kernel no generará un proceso zombie cuando finalice el proceso hijo. Esto es diferente de BSD4, que debe esperar explícitamente a que finalice el proceso zombie.

3. >

La instancia del proceso del demonio consta de dos partes: el programa principal test.c y el programa de inicialización init.c. El registro test.log en el directorio tmp informa el estado de ejecución. La función init_daemon en el programa de inicialización es responsable. para generar el proceso demonio. Los lectores pueden usar la función init_daemon para generar su propio proceso demonio.

1. lista init.c

#include lt; unistd.h gt;

#include lt; .h gt;

#include lt; sys/types.h gt;

#include lt; vacío)

{

int pid

int i

if(pid=fork())

exit(0); //Es el proceso padre, finaliza el proceso padre

else if(pidlt; ​​​​0)

exit(1); falló, salió

p>

//Es el primer proceso hijo y continúa ejecutándose en segundo plano

setsid() //El primer proceso hijo se convierte en el nuevo líder de sesión y líder del proceso

//Y separado del terminal de control

if(pid=fork())

exit(0); proceso hijo, finalice el primer proceso hijo

else if(pidlt; ​​​​0)

exit(1); //fork falló, salir

/ /Es el segundo proceso hijo, continuar

//El segundo proceso hijo ya no es el líder de la sesión

for(i=0; ilt; NOFILE; i)//Cerrar el descriptor de archivo abierto

close( i);

chdir("/tmp"); //Cambie el directorio de trabajo a /tmp

umask(0). ); //Restablecer la máscara de creación de archivos

return;

}

2. lista test.c

#include lt; stdio.h gt;

#include time.h gt

void init_daemon(void);/ /Función de inicialización del demonio

main()

{

FILE *fp

time_t t; init_daemon(); //Inicializar como Daemon

while(1)//Informar el estado de ejecución a test.log cada minuto

{

sleep ( 60); //Duerme un minuto

if((fp=fopen("test.log","a")) gt;=0)

{

t=time(0);

fprintf(fp, "Estoy aquí en sn", asctime(localtime(amp; t))

fclose); (fp);

}

}

}

El programa anterior fue compilado y pasado bajo RedHat Linux6.0. Los pasos son los siguientes:

Compilar: gcc –g –o test init.c test.c

Ejecutar: ./test

Ver el proceso: ps –ef

A partir del resultado, se puede encontrar que varias características del demonio de prueba cumplen con los requisitos anteriores.