¿Cuál fue la razón de la no preferencia de los antiguos núcleos de Linux?

15

¿Por qué los primeros desarrolladores de Linux eligieron implementar un kernel no preventivo? ¿Es para guardar la sincronización?

Hasta donde sé, Linux se desarrolló a principios de los 90, cuando las PC tenían un único procesador. ¿Qué ventaja ofrece un kernel no preventivo en tales PC? ¿Por qué, sin embargo, la ventaja es reducida por los procesadores multi-core?

Narden
fuente

Respuestas:

25

En el contexto del kernel de Linux, cuando las personas hablan sobre la preferencia, a menudo se refieren a la capacidad del kernel para interrumpirse a sí mismo, esencialmente, cambiar las tareas mientras se ejecuta el código del kernel. Permitir que esto suceda es bastante complejo, lo cual es probablemente la razón principal por la que tomó mucho tiempo para que el kernel se hiciera preejecutable.

Al principio, la mayoría del código del kernel no se podía interrumpir de todos modos, ya que estaba protegido por el gran bloqueo del kernel. Ese bloqueo se eliminó progresivamente de más y más código del núcleo, permitiendo múltiples llamadas simultáneas al núcleo en paralelo (lo que se hizo más importante a medida que los sistemas SMP se volvieron más comunes). Pero eso todavía no hizo que el núcleo en sí mismo fuera preejectable; eso tomó más desarrollo aún, culminando en el PREEMPT_RTconjunto de parches que finalmente se fusionó en el núcleo de la línea principal (y de todos modos era capaz de adelantarse al BKL). Hoy en día, el kernel se puede configurar para que sea más o menos preferible, dependiendo de las características de rendimiento y latencia que esté buscando; vea la configuración del kernel relacionada para más detalles.

Como puede ver en las explicaciones en la configuración del kernel, la preferencia afecta el rendimiento y la latencia, no la concurrencia. En los sistemas de CPU única, la opción preventiva sigue siendo útil porque permite procesar eventos con tiempos de reacción más cortos; sin embargo, también da como resultado un rendimiento menor (ya que el kernel pasa tareas de cambio de tiempo). La opción preventiva permite que cualquier CPU dada, en un sistema de CPU simple o múltiple, cambie a otra tarea más rápidamente. El factor limitante en los sistemas con múltiples CPU no es el de preferencia, son bloqueos, grandes o de otro tipo: cada vez que el código se bloquea, significa que otra CPU no puede comenzar a realizar la misma acción.

Stephen Kitt
fuente
11

El kernel preventivo solo significa que no hay Big Kernel Lock .

Linux tenía multitarea preventiva (es decir, el código de usuario era preferente) desde su primer momento (que yo sepa, el primer Linux 0.0.1 subido por Linus al servidor ftp de funet ya era multitarea preventiva). Si ejecutó, por ejemplo, múltiples procesos de compresión o compilación, se ejecutaron en paralelo desde el primer momento.

Contrariamente a la, en ese momento, ampliamente utilizada Win31. En Win31, si una tarea obtuvo la CPU del "núcleo", por defecto era su responsabilidad determinar cuándo devolver el control al sistema operativo (u otras tareas). Si un proceso no tenía soporte especial para esta característica (que requería trabajo de programación adicional), entonces mientras se ejecutaba, todas las demás tareas se suspendían. Incluso la mayoría de las aplicaciones básicas integradas en Win31 funcionaron así.

La multitarea preventiva significa que las tareas no tienen forma de asignar la CPU como desean. En cambio, si su intervalo de tiempo caduca, el kernel les quita la CPU. Por lo tanto, en los sistemas operativos preventivos, un proceso mal escrito o que funciona mal no puede congelar el sistema operativo o evitar que se ejecuten otros procesos. Linux siempre fue preventivo para los procesos de espacio de usuario.

El Big Kernel Lock significa que en algunos casos, dentro del espacio del kernel , todavía podría haber algunos bloqueos, evitando que otros procesos ejecuten el código protegido. Por ejemplo, no podría montar varios sistemas de archivos al mismo tiempo: si daba varios comandos de montaje, aún se ejecutaban consecutivamente, porque era necesario montar los elementos para asignar Big Kernel Lock.

Hacer que el kernel sea preventivo había requerido eliminar este gran bloqueo del kernel, es decir, hacer que el montaje y cualquier otra tarea pudieran ejecutarse simultáneamente. Fue un gran trabajo.

Históricamente, esto se hizo realmente urgente por el creciente soporte de SMP (soporte multi-CPU). En la primera vez, había realmente placas base de múltiples CPU. Más tarde, se integraron múltiples CPU ("núcleos") en un solo chip, hoy las placas base realmente multi-CPU ya son raras (generalmente están en sistemas de servidores costosos). Además, los sistemas realmente de un solo núcleo (donde solo hay una única CPU, con un solo núcleo) son raros.

Por lo tanto, la respuesta a su pregunta no es "cuál fue la razón de la no preferencia", porque siempre fue preventiva. La verdadera pregunta es qué hizo que la ejecución preventiva del núcleo fuera realmente necesaria . La respuesta es para eso: la relación creciente de los sistemas con muchas CPU y muchos núcleos.

peterh - Restablece a Monica
fuente
Realmente no entendí :( Hasta la versión 2.4 del kernel, solo los procesos del usuario eran preventivos y el kernel no era preventivo. Como respondí a alguien antes, creo que la razón era para salvar el trabajo en los bloqueos de sincronización que podrían ocurrir con preventivo implementación en el proceso de núcleo único. ¿Qué opinas?
Narden
@Narden No sé dónde lo leíste. Aproximadamente hasta 1.3 o 2.0, solo un solo proceso podría estar en el espacio del kernel, incluso si se ejecutaran múltiples procesos. Esta limitación fue eliminada aproximadamente con 2.0. Hasta alrededor de 2.4, había un Big Kernel Lock (es decir, el montaje simultáneo de múltiples sistemas de archivos no funcionaba).
peterh - Restablecer Monica
@Narden Pero no es una multitarea cooperativa, nunca se necesitó ningún proceso para devolver intencionalmente la CPU al programador de tareas. Sí, es probable que la razón de BKL sea que hacer esto correctamente es mucho trabajo: 1) los bloqueos deben dividirse 2) las estructuras de datos sin bloqueo deben usarse si es posible 3) los bloqueos divididos conducen a puntos muertos / livelocks, generalmente son errores sucios y difíciles de corregir, todos deben ser encontrados y reparados 4) todos los controladores deben ser portados a los cambios en la API del núcleo del núcleo.
peterh - Restablecer Monica
Lo leí mientras buscaba una respuesta, y también se da como información en un curso que estoy tomando, llamado Sistemas operativos.
Narden
1
El Big Kernel Lock evitó que otros hilos ingresaran al kernel cuando uno se estaba ejecutando en el kernel. Solo se permitió un subproceso, porque el núcleo no se diseñó desde el principio teniendo en cuenta el multiprocesamiento simétrico. Sin embargo, un núcleo preventivo significa algo diferente. Tradicionalmente, el contexto de ejecución se cambiaba solo cuando el núcleo volvía al espacio del usuario. En un núcleo preventivo, un subproceso puede ser eliminado en el medio de la ejecución del código del núcleo.
Johan Myréen
3

Esta no es una respuesta técnica, sino una respuesta histórica a la pregunta específica planteada por el OP: "¿Cuál fue la razón de la no preferencia de los núcleos Linux más antiguos?"

(Supongo, como explica @peterh en su respuesta y comentarios, que por "no preferencia" el OP se refiere a uno o ambos del hecho de que solo un proceso de usuario podría estar dentro del núcleo (en una API) en un tiempo y / o Big Kernel Lock.)

Linus Torvalds estaba interesado en aprender cómo funcionaban los sistemas operativos, y la forma en que aprendió fue escribir uno. Su modelo, base y entorno de desarrollo inicial era Minix, un sistema operativo existente para fines educativos (es decir, no un sistema operativo de producción) que no era gratuito (como en código abierto, en ese momento, no era gratis como en cerveza, ya sea).

Así que escribió un kernel sin preferencia (el Big Kernel Lock mencionado en otras respuestas) porque esa es la forma en que lo hace si desea que su nuevo sistema operativo funcione rápidamente con fines educativos: es mucho, mucho, mucho más simple de esa manera. Un núcleo para admitir la multiprogramación simultánea de programas y dispositivos de usuario es bastante difícil: es extremadamente difícil hacer que el núcleo mismo sea concurrente.

Si hubiera sabido qué tan popular / útil / importante sería Linux ... probablemente lo habría hecho de la misma manera. (Solo en mi opinión, no tengo idea de lo que realmente piensa). Porque tienes que caminar antes de poder correr.

Y se mantuvo así durante mucho tiempo porque a) había mucho trabajo por hacer para hacer de Linux lo que es hoy (o incluso lo que era entonces) yb) cambiarlo sería una tarea muy difícil (como se explica en otras respuestas).

davidbak
fuente