GNU/Linux >> Tutoriales Linux >  >> Linux

¿Qué significa decir que el kernel de Linux es preventivo?

Los núcleos tradicionales de Unix tenían un solo bloqueo, que estaba en manos de un subproceso mientras se ejecutaba el código del núcleo. Por lo tanto, ningún otro código del núcleo podría interrumpir ese hilo.

Esto facilitó el diseño del kernel, ya que sabía que mientras un subproceso usaba los recursos del kernel, ningún otro subproceso lo hacía. Por lo tanto, los diferentes subprocesos no pueden estropear el trabajo de los demás.

En sistemas de un solo procesador esto no causa demasiados problemas.

Sin embargo, en los sistemas multiprocesador, podría tener una situación en la que varios subprocesos en diferentes procesadores o núcleos quisieran ejecutar el código del kernel al mismo tiempo. Esto significa que, según el tipo de carga de trabajo, podría tener muchos procesadores, pero todos pasan la mayor parte del tiempo esperándose unos a otros.

En Linux 2.6, los recursos del kernel se dividieron en unidades mucho más pequeñas, protegidas por bloqueos individuales, y el código del kernel se revisó para asegurarse de que los bloqueos solo se mantuvieran mientras los recursos correspondientes estaban en uso. Así que ahora los diferentes procesadores solo tienen que esperar el uno al otro si quieren acceder al mismo recurso (por ejemplo, recurso de hardware).


Antes de la versión 2.5.4 del kernel de Linux, el kernel de Linux no era preventivo, lo que significa que un proceso que se ejecuta en modo kernel no se puede mover fuera del procesador hasta que deje el procesador o comience a esperar que se complete alguna operación de entrada y salida.

Generalmente, un proceso en modo usuario puede entrar en modo kernel mediante llamadas al sistema. Anteriormente, cuando el kernel no era preventivo, un proceso de menor prioridad podía invertir la prioridad de un proceso de mayor prioridad al negarle el acceso al procesador llamando repetidamente a las llamadas del sistema y permaneciendo en el modo kernel. Incluso si el intervalo de tiempo del proceso de menor prioridad expiraba, continuaría ejecutándose hasta que completara su trabajo en el núcleo o renunciara voluntariamente al control. Si el proceso de mayor prioridad que espera ejecutarse es un editor de texto en el que el usuario está escribiendo o un reproductor de MP3 listo para recargar su búfer de audio, el resultado es un rendimiento interactivo deficiente. De esta manera, el kernel no preventivo era un gran inconveniente en ese momento.


Imagine la vista simple de la multitarea preventiva. Tenemos dos tareas de usuario, las cuales se ejecutan todo el tiempo sin usar E/S ni realizar llamadas al kernel. Esas dos tareas no tienen que hacer nada especial para poder ejecutarse en un sistema operativo multitarea. El kernel, generalmente basado en una interrupción del temporizador, simplemente decide que es hora de que una tarea se detenga para permitir que otra se ejecute. La tarea en cuestión es completamente inconsciente de que sucedió algo.

Sin embargo, la mayoría de las tareas realizan solicitudes ocasionales del núcleo a través de llamadas al sistema. Cuando esto sucede, existe el mismo contexto de usuario, pero la CPU está ejecutando el código del kernel en nombre de esa tarea.

Los kernels de Linux más antiguos nunca permitirían la preferencia de una tarea mientras estaba ocupado ejecutando el código del kernel. (Tenga en cuenta que las operaciones de E/S siempre se reprograman voluntariamente. Me refiero a un caso en el que el código del kernel tiene alguna operación que requiere un uso intensivo de la CPU, como ordenar una lista).

Si el sistema permite que esa tarea sea reemplazada mientras se ejecuta el código del kernel, entonces tenemos lo que se llama un "núcleo preventivo". Dicho sistema es inmune a los retrasos impredecibles que se pueden encontrar durante las llamadas al sistema, por lo que podría ser más adecuado para tareas integradas o en tiempo real.

Por ejemplo, si en una CPU en particular hay dos tareas disponibles, y una toma una llamada al sistema que tarda 5 ms en completarse, y la otra es una aplicación de reproductor de MP3 que necesita alimentar la tubería de audio cada 2 ms, es posible que escuche un audio entrecortado.

El argumento en contra de la preferencia es que todo el código del kernel que podría llamarse en el contexto de la tarea debe poder sobrevivir a la preferencia; hay mucho código de controlador de dispositivo deficiente, por ejemplo, que podría estar mejor si siempre puede completar una operación antes permitiendo que alguna otra tarea se ejecute en ese procesador. (Con los sistemas multiprocesador, la regla en lugar de la excepción en estos días, todo el código del núcleo debe volver a entrar, por lo que ese argumento no es tan relevante hoy). Además, si se pudiera lograr el mismo objetivo mejorando las llamadas al sistema con malas latencia, tal vez la prioridad sea innecesaria.

Un compromiso es CONFIG_PREEMPT_VOLUNTARY, que permite un cambio de tarea en ciertos puntos dentro del núcleo, pero no en todas partes. Si solo hay una pequeña cantidad de lugares en los que el código del kernel podría atascarse, esta es una forma económica de reducir la latencia y mantener la complejidad manejable.


La preferencia permite que el kernel dé la IMPRESIÓN de paralelismo:solo tiene un procesador (digamos hace una década), pero siente que todos sus procesos se ejecutan simultáneamente. Esto se debe a que el núcleo se adelanta (es decir, quita la ejecución de) la ejecución de un proceso para dársela al siguiente (quizás según su prioridad).

EDITAR Los núcleos no preventivos esperan a que los procesos devuelvan la mano (es decir, durante las llamadas al sistema), por lo que si su proceso calcula una gran cantidad de datos y no llama a ningún tipo de yield función, los otros procesos no podrán ejecutar para ejecutar sus llamadas. Se dice que estos sistemas son cooperativos porque piden la cooperación de los procesos para asegurar la equidad del tiempo de ejecución

EDITAR 2 El objetivo principal de la preferencia es mejorar la reactividad del sistema entre múltiples tareas, por lo que es bueno para los usuarios finales, mientras que, por otro lado, los servidores quieren lograr el mayor rendimiento, por lo que no lo necesitan:(de la configuración del kernel de Linux)

  • Kernel interrumpible (escritorio de baja latencia)
  • Apropiación voluntaria del kernel (escritorio)
  • Sin prioridad forzada (servidor)

Linux
  1. ¿Qué significa EXPORT_SYMBOL en el código del kernel de Linux?

  2. ¿Qué es mejor int 0x80 o syscall en código de 32 bits en Linux?

  3. ¿Cómo codificar un módulo del kernel de Linux?

  4. ¿Qué significa &al final de un comando de Linux?

  5. ¿Qué pasa si [[ $? -ne 0 ]]; significa en .ksh

¿Qué significa nulo en Linux y Computación?

¿Qué significa el comando Cat en Linux?

Qué hacer en caso de pánico en el kernel de Linux

Linux:¿a qué nos referimos exactamente cuando decimos que estamos usando Linux?

¿Qué significa ./ (punto barra oblicua) en Linux?

¿Qué significa el sufijo .d en Linux?