Introducción al kernel Linux
Matías Zabaljáuregui
[email protected]
● Repaso del modelo kernel / proceso
● Contextos de ejecución
● Kernels Unix y Linux
● Reentrancia y Sincronización
● Diferencias con el user space
Repaso:
¿Que es el Kernel?
● El kernel como máquina ampliada o maquina virtual: proveé
un entorno de ejecución a las aplicaciones.
● El kernel como manejador de recursos: interactúa con la
plataforma de hardware.
El Modelo Proceso / Kernel
● Los procesos son entidades dinámicas, programas en
ejecución que consumen recursos.
● El kernel es un administrador de procesos que crea el
entorno necesario para que los procesos puedan
ejecutarse.
● El modelo asume que los procesos que requieren un
servicio del kernel utilizan construcciones específicas
llamadas system calls.
● Se necesita soporte del hardware para implementar el
modelo con dos estados de la CPU: uno privilegiado y uno
no privilegiado.
User Mode vs Kernel Mode
● Una CPU tiene distintos modos de ejecución, con distintos
privilegios. Por ejemplo x86 tiene 4 niveles de privilegios.
● El modelo que estudiamos utiliza dos modos de ejecución.
● Cuando un programa se ejecuta en User Mode tiene ciertas
reestricciones de acceso a memoria o hardware.
● Cuando una rutina se ejecuta en Kernel Mode accede a
todos los recursos sin restricciones.
● Cada tipo de CPU proveé instrucciones especiales para
pasar de User Mode a Kernel Mode y viceversa.
Kernel Space vs User Space
● El kernel vive en un estado elevado del sistema, comparado con
las aplicaciones del usuario. Este estado, que incluye un espacio
de memoria protegido, acceso pleno al hardware y el procesador
ejecutando en Kernel Mode, es conocido como Kernel Space.
● Por otro lado las aplicaciones de usuario se ejecutan en el User
Space. Sólo ven un subconjunto de los recursos de la máquina y
no pueden realizar ciertas funciones directamente. En este
estado el procesador se ejecuta en User Mode.
● Un programa normalmente se ejecuta en User Space y cambia al
Kernel Space sólo cuando requiere un servicio provisto por el
kernel. Cuando el kernel satisface el pedido, vuelve a setear el
procesador en User Mode y la aplicación vuelve a ejecutarse en
User Space.
System Calls
● Las aplicaciones invocan funciones del kernel a través de las
System Calls. Típicamente se llaman a funciones de librerías, las
cuales invocan systems calls para realizar su trabajo.
● Algunas funciones de librerías invocan a más de una system call o
llaman a una system call sólo como un paso en su procesamiento.
Ejemplo: printf().
● Algunas funciones tienen una relación de uno a uno con system calls.
Ejemplo: open().
● Otras funciones, no deberían hacer uso de system calls. Por ejemplo:
strcpy ().
● En una system call, se dice que el kernel se está ejecutando en
nombre de la aplicación. Es más, se dice que la aplicación está
ejecutando una función en kernel space y el kernel está corriendo
en el contexto del proceso de usuario (process context).
Relación entre procesos, kernel
y hardware
Interrupciones y Excepciones
● Una interrupción suele ser definida como un evento que altera la
secuencia de instrucciones ejecutadas por un procesador. Esos eventos
corresponden a señales eléctricas generadas por hardware desde
dentro y fuera de la CPU.
● Suelen clasificarse en:
Excepciones: producidas por la unidad de control de la CPU.
Interrupciones: generadas por otros dispositivos de hardware.
● Cuando una señal de interrupción llega a la CPU, el kernel debe realizar
ciertas tareas que generalmente son implementadas desde un módulo
llamado manejador de interrupción.
Interrupt Context
● Los manejadores de interrupciones no se ejecutan en el
contexto de un proceso.
● En cambio, se ejecutan en un contexto especial de
interrupción, pero los ciclos de CPU consumidos se
computan al proceso interrumpido.
● Este contexto existe únicamente para permitir que un
manejador responda rápidamente a una interrupción y luego
termina.
Contextos de Ejecución
del Kernel (vistos hasta ahora)
● Estos contextos representan momentos de actividad del
kernel.
● De hecho, en Linux, se puede generalizar que cada
procesador de una máquina está haciendo alguna de estas
tres cosas en un momento dado:
● En kernel space, en “process context”, ejecutando en
nombre de algún proceso.
● En kernel space, en “interrupt context”, manejando una
interrupción.
● En user space, ejecutando código de un proceso de
usuario.
Kernel Threads
Además de procesos de usuario, Linux incluye algunos
“procesos” privilegiados, con las siguientes características:
● Normalmente son creados durante el arranque del sistema
y permanecen vivos hasta que se apaga la máquina.
● Corren en kernel space, no necesitan tablas de página para
mapear memoria de usuario
● No interactúan con usuarios, por lo que no requieren
dispositivos de E/S (terminales)
● Contexto más liviano, por lo tanto el switch es más rápido
que el de un proceso de usuario
Funciones Diferibles
● El manejador de interrupciones no es un contexto en el que
puedan realizarse cualquier tipo de acción. Por ejemplo, no debe
bloquearse nunca.
● Las operaciones largas y no críticas deberían ser diferidas ya que
mientras el manejador se está ejecutando, las señales en la línea
IRQ correspondiente son temporalmente ignoradas.
● Linux implementa esto usando dos tipos de funciones diferibles
(“bottom halves”) del kernel: “softirqs” y “tasklets”
● Este tipo de funciones suele ser planificada por el programador
desde un manejador de interrupciones (o de otro contexto) para
que se ejecute asincrónicamente en algún momento “seguro”
(elegido por el kernel) en el futuro cercano.
Contextos de Ejecución del
Kernel (Completo)
● Un proceso invoca una system call.
● Una CPU ejecutando un proceso eleva una excepción. El
kernel maneja la excepción “en nombre” del proceso que la
causó.
● Un dispositivo eleva una señal de interrupción a la CPU
para indicar que se completó una operación de E/S.
● Un kernel thread es elegido por el scheduler.
● Una softirq es ejecutada.
Ejemplo de ejecución
Kernels Unix y Linux
● Debido a sus antepasados comunes, los kernels Unix modernos,
además de sus APIs comparten varias cuestiones de diseño.
● Con algunas excepciones, un kernel Unix es típicamente un
binario monolítico y estático. Es decir, existe como una imagen
ejecutable única y de gran tamaño que corre en un único
espacio de direccionamiento
● Los sistemas Unix normalmente requieren hardware de
administración de memoria (MMU) el cual proveé protección de
memoria y un espacio virtual único a cada proceso. Linux tiene
sus variantes para hardware embebido. Ejemplo: uClinux.
Diseño Monolítico versus Microkernels
Existen dos grandes clasificaciones de kernels con respecto a
su diseño:
● kernels monolíticos
● microkernels
Otras categorías, nanokernels, exokernels, etc, se
mencionan principalmente en entornos de investigación.
Kernels Monolíticos
● Representan el diseño más simple y fue la única opción hasta
los 80s.
● Se implementan en forma de un gran “programa” corriendo en un
único espacio de direccionamiento.
● La comunicación dentro del kernel es trivial porque todo corre en
kernel space en el mismo espacio de direccionamiento: se
invocan funciones.
● Los defensores de este modelo citan la simplicidad y
performance como principales ventajas.
● La mayoria de los kernels Unix son monolíticos.
Microkernels
● La funcionalidad del kernel está distribuida entre procesos
separados, usualmente llamados servers.
● En teoría, sólo los procesos que realmente lo requieren son los
que deberían ejecutarse en kernel space, y el resto en user
space.
● Se incluye algún mecanismo de comunicación entre procesos,
que ofrece comunicación entre servers a través de mensajes.
● Diseño modular. Permite fácil reemplazo de subsistemas.
Microkernels
Existen costos asociados al modelo:
● Pasaje de mensajes tiene mayor overhead que invocacion directa
a funcion.
● Se producen context switches de kernelspace a userspace y
viceversa
En consecuencia, todos los sistemas basados en microkernels
ahora ejecutan sus servers en kernel space. El kernel de
Windows NT y Mach son ejemplos de microkernels y ninguno
corre los servers en user space en sus últimas versiones.
Linux: monolítico moderno
Linux es un kernel monolítico, sin embargo, toma muchas de las
buenas ideas de los microkernels:
● Diseño modular
● Scheduleable / preemptible (KCPs)
● Soporte para kernel threads
● Modulos Dinámicos en demanda
Por otro lado, no sufre de la pérdida de performance asociada al
modelo de microkernel:
● Todo corre en kernel mode
● La comunicación es a través de invocaciones funciones
Ejemplos
Kernels Monolíticos:
● Linux
● Kernels Unix tradicionales, como los BSDs
● Solaris
Microkernels famosos:
● Aix (IBM eServers pSeries, utilizando procesadores de la familia IBM POWER de 32 y 64bits)
● Minix
● Mach, usado en GNU Hurd y Mac OS X entre otros
● QNX (real time)
Reentrancia
● Todos los kernels Unix son reentrantes, es decir, más de un
proceso puede estar en kernel mode a la vez
● Si ocurre una interrupción de hardware, un kernel reentrante es
capaz de suspender el proceso que se está ejecutando en ese
momento, aunque esté en kernel mode. Esta capacidad es
importante para lograr eficiencia.
● Una forma de lograr reentrancia es usar sólo funciones
reentrantes (como lo hacen algunos kernels de tiempo real),
aunque esto no es siempre posible.
● Otra forma es permitir funciones no reentrantes y utilizar
mecanismos de locking.
Reentrancia y su impacto en la
organización del kernel
● Un camino de control del kernel (KCP) denota una secuencia de
instrucciones ejecutadas por el kernel. En el caso más simple, el kernel
ejecuta un K
Comentarios de: Introducción al kernel Linux (1)