Servidor ejecutándose en el kernel de linux. ¿Debería escucharse pasar en un hilo o no?

StackOverflow https://stackoverflow.com/questions/615483

  •  03-07-2019
  •  | 
  •  

Pregunta

Estoy escribiendo un cliente / servidor en el kernel de Linux (Sí. Dentro del kernel. La decisión de diseño se tomó y finalizó. No va a cambiar)

El servidor lee los paquetes entrantes desde un socket en bruto. El protocolo de transporte para estos paquetes (en el que se escucha el socket sin procesar) es personalizado y similar a UDP. En resumen, no tengo que escuchar las conexiones entrantes y luego desviar un hilo para manejar esa conexión.

Tengo que procesar cualquier datagrama IP que venga a ese socket sin procesar. Seguiré leyendo los paquetes en un bucle infinito en el socket sin procesar. En el programa equivalente de nivel de usuario, habría creado un hilo separado y seguido escuchando los paquetes entrantes.

Ahora, para el servidor de nivel de kernel, tengo dudas sobre si debo ejecutarlo en un hilo separado o no porque:

  1. Creo que read () es una operación de E / S. Entonces, en algún lugar dentro de la lectura (), el kernel debe llamar a la función schedule () para renunciar al control del procesador. Por lo tanto, después de llamar a read () en el socket sin procesar, el contexto activo actual del kernel se pondrá en espera (¿se pondrá en una cola de espera?) Hasta que los paquetes estén disponibles. Cuando lleguen los paquetes, el contexto de interrupción del kernel indicará que el contexto de lectura, que está en espera en la cola, está nuevamente listo para ejecutarse. Estoy usando 'contexto' aquí a propósito en lugar de 'hilo'. Por lo tanto, no debería requerir un hilo del kernel separado.

  2. Por otra parte, si read () no abandona el control, se bloqueará todo el núcleo.

¿Alguien puede dar consejos sobre cómo debo diseñar mi servidor? ¿Cuál es la falacia del argumento presentado en el punto 1?

¿Fue útil?

Solución

No estoy seguro de si necesitas un socket en bruto en el núcleo. Dentro del kernel puede agregar un gancho de filtro de red, o registrar otra cosa (???) que recibirá todos los paquetes; esto podría ser lo que quieres.

Si DID usa un socket en bruto dentro del kernel, entonces es probable que necesite un hilo del kernel (es decir, iniciado por kernel_thread) para llamar a read (). Pero no es necesario que sea un subproceso del kernel, podría ser un subproceso del espacio de usuario que acaba de hacer una llamada especial a syscall para llamar a la rutina deseada en modo kernel.

Si tiene un enlace registrado, el contexto en el que se llama es probablemente algo que no debería hacer demasiado procesamiento; No sé exactamente lo que es probable que sea, puede ser un " controlador de la mitad inferior " o " tasklet " ;, cualquiera que sea (estos tipos de estructuras de control cambian de una versión a otra). Espero que no sea realmente una rutina de servicio de interrupción.


En respuesta a tu pregunta original:

  1. Sí, sys_read bloqueará el subproceso de llamada, ya sea un subproceso del núcleo o un espacio de usuario. El sistema no se cuelga. Sin embargo, si el subproceso que realiza la llamada no se encuentra en un estado en el que el bloqueo tenga sentido, el kernel entrará en pánico (la programación se interrumpe o algo así)

Sí, deberá hacer esto en un hilo separado, no, no bloqueará el sistema. Sin embargo, hacer llamadas al sistema en modo kernel es muy dudoso, aunque funciona (más o menos).

Pero si instalaste algún tipo de gancho, no necesitarías hacer nada de eso.

Otros consejos

Creo que lo mejor que puede hacer es emular la forma en que se escriben los controladores, piense en su servidor como un dispositivo virtual que se encuentra sobre los dispositivos de los que provienen las solicitudes. Ejemplo: un controlador de mouse acepta entrada continua, pero no bloquea el sistema si está programado correctamente, y un adaptador de red es probablemente más similar a su caso.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top