0% encontró este documento útil (0 votos)
24 vistas29 páginas

Estudio del Kernel de Linux

Este documento describe los componentes y características del núcleo de Linux. Explica que el kernel gestiona los recursos hardware, asigna memoria y tiempo de procesamiento a los programas, y actúa como interfaz entre el hardware y software. También cubre los componentes clave del kernel como el manejo de procesos, memoria, archivos y comunicación entre procesos.

Cargado por

Brandón Suárez
Derechos de autor
© All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como DOCX, PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
24 vistas29 páginas

Estudio del Kernel de Linux

Este documento describe los componentes y características del núcleo de Linux. Explica que el kernel gestiona los recursos hardware, asigna memoria y tiempo de procesamiento a los programas, y actúa como interfaz entre el hardware y software. También cubre los componentes clave del kernel como el manejo de procesos, memoria, archivos y comunicación entre procesos.

Cargado por

Brandón Suárez
Derechos de autor
© All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como DOCX, PDF, TXT o lee en línea desde Scribd

Universidad Mexiquense del Bicentenario

Plantel Jiquipilco

Ingeniería en Sistemas Computacionales

Asignatura: Sistemas Operativos.

Estudiante: Brandon Suarez Guerrero.

Matricula: 10190061

Grupo: 10SC171.

Docente: I.S.C. Elizabeth Medina Morales

Actividad: Estudio de caso Núcleo de Sistema operativo GNU-

Linux.

Jiquipilco, 19, septiembre 2022.


Linux Kernel

“El kernel es el paradigma que reside en memoria y le indica al CPU que hacer.
Este núcleo gestiona al hardware y actúa como una interfaz entre éste y cualquier
programa en ejecución” (Lovk, 2010, pág. 140).

“El núcleo de Linux se posiciona directamente en el hardware y permite las


interacciones con los dispositivos de E/S y la unidad de administración de la
memoria; además controla el acceso de la CPU a estos dispositivos” (Bovet &
Cesati, 2006, pág. 19).

“El kernel es responsable de tareas de bajo nivel como administración de discos,


la administración de la memoria, la administración de tareas, etcétera. Proporciona
una interfaz entre el usuario y los componentes del hardware” (Deitel, 1993, pág.
80).

Componentes del kernel

Según el investigador Antonio Vázquez, “Actualmente Linux es un núcleo


monolítico híbrido. Los controladores de dispositivos y las extensiones del núcleo
normalmente se ejecutan en un espacio privilegiado conocido como anillo 0 (ring
0), con acceso irrestricto al hardware” (Vázquez, 2004, pág. 3).

“El kernel Linux se ejecuta en el anillo de protección 0:

Ilustración 1: Componentes del Kernel de Linux. Fuente: Administración avanzada (ENI, 2009);
NOTA: Este núcleo gestiona recursos mediante servicios de llamada al sistema operativo y decide
cuáles son los programas que harán uso de un dispositivo de hardware y cuál será su duración,
distribuyendo los recursos de la mejor forma, para que los componentes externos e internos del
ordenador puedan trabajar en conjunto. Otra de sus funciones, es la de administrar la memoria de
los procesos y programas en ejecución.

 El Process Management (PM) que se encarga de repartir de forma equitativa


el acceso al procesador entre todas las aplicaciones activas.
 El Memory Management (MM) que se encarga de asignar a cada programa
una zona de memoria que no debe ser leída o modificada por otro proceso.
 El Virtual File System (VFS) que garantiza una gestión correcta de los
archivos y un control de los permisos de acceso (ACL - Access Control List).
Para reducir la complejidad asociada a los múltiples sistemas de archivos
existentes, el kernel emplea llamadas de sistema idénticas e independientes
del sistema de archivos escogido. El kernel de Linux encamina los comandos
o llamadas estándar a las llamadas específicas del sistema de archivos.
 El Inter-Process Communication (IPC) permite a las aplicaciones comunicarse
entre sí de forma que un proceso solo pueda acceder a la zona de memoria
que tiene asignada.
 El Device Driver (DD) administra los recursos hardware con los controladores
de dispositivos (device drivers) y proporciona a los programas una interfaz
uniforme para el acceso a estos recursos” (Vázquez, 2004, pág. 22).

Funciones del kernel

Según el autor Robert Lovk, “Las principales funciones del Kernel son las
siguientes:”

 Administra la memoria RAM, para que todos los programas y procesos en


ejecución puedan funcionar.
 Administra el tiempo del procesador, que se utiliza al ejecutar procesos.
 Administra el acceso y uso de los diferentes periféricos conectados a la
computadora.
 Llamadas al sistema y seguridad: recibe peticiones de servicio de los
procesos.
 Acceso a los recursos del equipo: un núcleo puede acceder a varios recursos,
como la CPU, los dispositivos de entrada y salida, entre otros recursos. Actúa
como un puente entre el usuario y los recursos del sistema.
 Gestión de recursos: Es deber de un núcleo compartir los recursos entre
varios procesos de tal manera que haya un acceso uniforme a estos”. (Lovk,
2010, pág. 18).

Antecedentes
Según la investigadora Sofia Solorzano, “Linux es el nombre del núcleo del
sistema operativo que se atribuye a Linus Torvals, quien usaba un sistema basado
en Unix llamado Minix, e intentaba implementar este sistema en una máquina 386
utilizando el lenguaje C y varias herramientas del proyecto GNU”.

Igualmente, la investigadora Solorzano refiere que “el resultado de este proyecto


fue la primera versión de Linux, una versión muy primitiva que no llegaría a
difundirse, más tarde, el 5 de octubre de 1991, en una conferencia sobre Minix,
Linus distribuyó gratuitamente entre los asistentes el código fuente de la versión
0.02 de Linux e invitó a todos a participar activamente en el proyecto.
Posteriormente, registra Linux bajo la licencia GPL General Public License,
promovida por el proyecto GNU. La combinación de Linux más todas las
herramientas GNU dio como resultado un sistema operativo muy robusto y
completo” (Solorzano, 2009, pág. 12).

Por su parte el autor Óscar Alemán señala que “fue un pequeño pero
autosuficiente núcleo (kernel) para el procesador 80386, el primer procesador de
32 bits verdadero en la gama de CPU compatibles con PC de Intel. El primer
núcleo Linux liberado al público fue la versión 0.01, fechada 14 de mayo de 1991.
Esta versión no trabajaba con redes, sólo se ejecutaba en procesadores Intel
compatibles con el 80386 y hardware de PC, y contaba con soporte de drivers de
dispositivos extremadamente limitado. El único sistema de archivos que se
reconocía era el de Minix” (Aleman, 2002, pág. 29).

Características
El autor Francisco Gonzalez describe algunas de las principales características del
kernel Linux:

 “El núcleo de Linux se implementa como un núcleo monolítico tradicional por


razones de desempeño, pero su diseño es lo bastante modular como para
permitir que la mayor parte de los controladores se cargue y descargue
dinámicamente durante la ejecución.
 En su diseño global, Linux semeja cualquier otra implementación tradicional
de UNIX que no sea en micronúcleo. Linux es un sistema multiusuario,
multitarea, con un conjunto completo de herramientas compatibles con UNIX.
 Los procesos recién creados pueden compartir partes selectas de su entorno
de ejecución con sus procesos padres, lo que hace posible la programación
multihilada (multithreaded). La comunicación entre procesos se apoya tanto
en los mecanismos de System V mediante colas de mensajes, semáforos y
memoria compartida - como en la interfaz de sockets de BSD.
 El código del núcleo se ejecuta en el modo privilegiado del procesador con
pleno acceso a todos los recursos físicos del computador. Linux llama a este
modo privilegiado modo de núcleo. Bajo Linux, no se incorpora código en
modo de usuario en el núcleo. Cualquier código de soporte del sistema
operativo que no necesite ejecutarse en modo de núcleo se coloca en las
bibliotecas del sistema” (González, 2004, pág. 41).

Por otra parte, el autor Jorge Peña señala que, “Linux conserva el modelo histórico
de UNIX: el núcleo se crea como un solo binario monolítico. La razón principal es
para mejorar el desempeño: dado que todo el código y las estructuras de datos del
núcleo se mantienen en un solo espacio de direcciones, no se requieren
conmutaciones de contexto32 cuando un proceso invoca una función del sistema
operativo o cuando se entrega una interrupción de hardware. No sólo el código de
planificación y memoria virtual central ocupan este espacio de direcciones; todo el
código del núcleo, incluido el de los drivers de dispositivos, sistemas de archivos y
trabajo con redes, está presente en el mismo espacio de direcciones único” (Peña,
2006, pág. 25).
Los autores Daniel Bovet y Marco Cesati destacan que, “en muchos sistemas
operativos actuales el núcleo es un proceso; y por lo tanto la forma de acceder al
sistema operativo es mediante un cambio de contexto, ya que el núcleo de Linux
NO es un proceso, en Linux el cambio de contexto se realiza bajo demanda. El
núcleo (el proceso en ejecución, dentro del núcleo) ejecuta una instrucción para
cambiar a otra tarea (que también estará en el núcleo, en el punto en el que se
quedó al ceder la CPU). Los procesos en Linux son rutinas dobles que se ceden el
procesador de forma explícita” (Bovet & Cesati, 2006, pág. 53).

Ilustración 2: Conmutación de contexto Linux. Fuente: Módulo 9: Núcleo de Linux (I.T.U, 2004).

NOTA: Una CPU tiene distintos modos de ejecución, con distintos privilegios. Por ejemplo x86
tiene 4 niveles de privilegios. El kernel de Linux utiliza 2 niveles de privilegios.

Módulos

De acuerdo con los autores Daniel Bovet y Marco Cesati, “el núcleo de Linux tiene
la facultad de cargar y descargar secciones arbitrarias del código del núcleo
cuando se le pide hacerlo. Estos módulos de núcleo cargables se ejecutan en
modo de núcleo privilegiado, y por ello tienen pleno acceso a todas las
capacidades de hardware de la máquina en la que se ejecutan. En teoría, no hay
restricción respecto a lo que se permite a un módulo de núcleo hacer; típicamente,
un módulo podría implementar un controlador de dispositivo, un sistema de
archivos o un protocolo de redes” (Bovet & Cesati, 2006, pág. 57).
Ilustración 3: Módulos. Fuente: Módulo 9: Núcleo de Linux (I.T.U, 2004).

NOTA: 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.

Procesos e hilos
El autor Francisco Gonzalez señala “que el núcleo de Linux maneja de forma
sencilla la diferencia entre procesos e hilos: utiliza exactamente la misma
representación interna para todos. Un hilo no es más que un proceso nuevo que
por casualidad comparte el mismo espacio de direcciones que su padre”
(González, 2004, pág. 14).

Planificación de procesos

Como expresan los investigadores Daniel Bovet y Marco Cesati, “El planificador es
el algoritmo responsable de repartir el uso del procesador o procesadores entre
todos los procesos activos del sistema. El algoritmo de planificación únicamente
tiene que decidir cuál será el siguiente proceso que utilizará el procesador (se
elige un proceso ganador entre todos los que no están bloqueados). El cambio de
contexto es el mecanismo que efectivamente pone en ejecución a un proceso.
Esta operación es muy dependiente de la arquitectura del procesador sobre el que
se esté ejecutando, por lo que se tiene que realizar a bajo nivel (en ensamblador)”

En el mismo sentido Daniel Bovet y Marco Cesati refieren que “una vez que el
núcleo llega a un punto de replanificación, debe decidir cuál proceso ejecutará a
continuación. Linux tiene dos algoritmos de planificación de procesos
independientes. Uno es un algoritmo de tiempo compartido para la planificación
expropiativa justa entre múltiples procesos, y el otro está diseñado para tareas en
tiempo real en las que las prioridades absolutas son más importantes que la
equitatividad” (Bovet & Cesati, 2006, pág. 116).

En el caso de procesos de tiempo compartido el autor Galvin Silverchatz, señala


que, “Linux usa un algoritmo con prioridades basado en créditos. Cada proceso
posee cierto número de créditos de planificación; cuando es preciso escoger una
nueva tarea para ejecutarla, se selecciona el proceso que tiene más créditos.
Cada vez que ocurre una interrupción de temporizador, el proceso que se está
ejecutando en ese momento pierde un crédito; cuando sus créditos llegan a cero,
se suspende y se escoge otro proceso” (Silverchatz, 2006, pág. 231).

Asimismo el autor Harvey Deitel agrega que en “Linux los procesos que se
ejecutan todo el tiempo tienden a agotar sus créditos rápidamente, pero los que
pasan una buena parte de su tiempo suspendidos pueden acumular créditos a lo
largo de varias renovaciones y por consiguiente terminarán con una mayor
cantidad de créditos después de una renovación. Este sistema de crédito da
prioridad automáticamente a los procesos limitados por E/S, para los cuales es
importante una respuesta rápida” (Deitel, 1993, pág. 84).

Multiprocesamiento simétrico

De acuerdo con el autor Óscar Alemán, “el núcleo de Linux 2.0 fue el primer
núcleo Linux estable que manejó hardware de multiprocesador simétrico (SMP,
symmetric multiprocessor). Procesos o hilos individuales se pueden ejecutar en
paralelo en procesadores distintos. Sin embargo, a fin de conservar los requisitos
de sincronización no expropiable del núcleo, la implementación de SMP en este
núcleo impone la restricción de que sólo un procesador a la vez puede estar
ejecutando código en modo de núcleo” (Aleman, 2002, pág. 11).

Gestión de memoria

EL autor Harvey Deitel señala que, “La memoria es uno de los recursos más
valiosos que administra el sistema operativo. Uno de los elementos principales
que caracterizan un proceso es la memoria que utiliza. Ésta está lógicamente
separada de la de cualquier otro proceso del sistema, excepto los threads de un
mismo proceso que comparten normalmente la mayor parte de la memoria que
tienen asignada. Un proceso no puede acceder, ni accidentalmente, al espacio de
memoria asignado a otro proceso, lo cual es imprescindible para la seguridad y
estabilidad del sistema. En Linux, además, un proceso tiene dos espacios de
memoria: el espacio de memoria del usuario, único para ese proceso, y el espacio
de memoria del núcleo, idéntico en todos los procesos” (Deitel, 1993, pág. 93).

Estructura de un núcleo de sistema operativo

Ilustración 4: Niveles en un sistema operativo. Fuente: Laboratorio de Sistemas Operativos


(UPV/EHU ATC, 2006).

NOTA: El kernel es un administrador de procesos que crea el entorno necesario para que los
procesos puedan ejecutarse.
Los procesos son  entidades  dinámicas, programas  en  ejecución  que consumen recursos. El
kernel se encarga principalmente de mediar entre los procesos de usuario y el hardware
disponible en la máquina, es decir, concede el acceso al hardware, al software que lo solicite, de
una manera segura; y el procesamiento paralelo de varias tareas.
Rutinas de manejo de colas y auxiliares

De acuerdo con el investigador Alberto Lafuente, “Fundamentalmente son rutinas


de acceso a colas con los accesos generales de encolar, desencolar, insertar,
vaciar y organizar” (Lafuente, 2006, pág. 5).

Ilustración 5: Rutinas auxiliares para manejo de colas. Fuente: Laboratorio de Sistemas Operativos
(UPV/EHU ATC, 2006).

NOTA: Rutinas auxiliares: son rutinas que se encargan de tareas auxiliares y que pueden ser de
utilidad para cualquier otra rutina (de servicio o auxiliar) del sistema operativo: manipulación de
estructuras de datos, comprobaciones habituales, etcétera.

Ilustración 6: Otras rutinas auxiliares. Fuente: Laboratorio de Sistemas Operativos (UPV/EHU ATC,
2006).

NOTA: El kernel Linux está programado en C en su mayoría y se usa assembly en las partes de
código de bajo nivel dependientes de la arquitectura y aquellas funcionalidades cuya eficiencia es
crítica.
Primitivas del núcleo
El autor Alberto Lafuente refiere que, “Las primitivas del núcleo constituyen el
conjunto de rutinas visibles desde el nivel superior. Se definen en C y utilizan las
rutinas dependientes del hardware y a las rutinas auxiliares” (Lafuente, 2006, pág.
7).

Ilustración 7: Primitivas del Núcleo. Fuente: Laboratorio de Sistemas Operativos (UPV/EHU ATC,
2006).

NOTA: Un conjunto de primitivas o llamadas al sistema núcleo todos los servicios del sistema
operativo, como la gestión de procesos, la concurrencia y la gestión de memoria. Los
controladores de dispositivos se pueden agregar al núcleo como módulos.
Funcionamiento del núcleo

“El kernel es el núcleo de un sistema operativo y, por tanto, la interfaz entre el


software y el hardware” (Deitel, 1993, pág. 95).

“Un kernel es la base de la interacción entre el hardware y el software y gestiona


sus recursos de la forma más eficiente posible” (Silverchatz, 2006, pág. 233).

Planificación de procesos

Según el investigador Alberto Lafuente, “Los procesos preparados para ejecución


se encolan en la cola ready de acuerdo con su prioridad, por lo que la rutina del
scheduler se limita a tomar el primer elemento de la cola, que pasa al dispatcher
para que lo cargue en ejecución (cola run, que tendrá un único elemento). Por
ortogonalidad, se asume la existencia de un proceso nulo, que siempre estará
preparado para ejecución o ejecutándose” (Lafuente, 2006, pág. 9).

La siguiente figura muestra el código de las rutinas scheduler() y el dispatcher().

Ilustración 8: Rutinas scheduler y dispatcher. Fuente: Laboratorio de Sistemas Operativos


(UPV/EHU ATC, 2006).

NOTA: Es el componente del núcleo encargado de la planificación. La necesidad de algoritmos de


planificación surgió con la aparición de sistemas operativos multi tareas.

“La rutina bloquear() es la encargada de sacar a un proceso de la cola, lo que


implica como efecto colateral la actualización del tiempo de CPU” (Lafuente, 2006,
pág. 9).
Ilustración 9: Rutina bloquear. Fuente: Laboratorio de Sistemas Operativos (UPV/EHU ATC, 2006).

NOTA: El bloqueo significa que la ejecución de su código (en ese hilo) se detendrá mientras dure
la llamada. Esencialmente, la llamada a la función no regresará hasta que se complete la
operación de bloqueo. Una lectura de bloqueo esperará hasta que haya datos disponibles (o hasta
que expire el tiempo de espera, si corresponde) y luego regresará de la llamada a la función.
Interrupciones y Excepciones
El autor Matías Zabaljáuregui, “Señala que 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”.

Además, Zabaljáuregui refiere que “suelen clasificarse en:

 “Excepciones: producidas por la unidad de control de la CPU.


 Interrupciones: generadas por otros dispositivos de hardware”
(Zabaljáuregui, 2008, pág. 9).

El autor Harvey Deitel enfatiza en que, “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” (Deitel,
1993, pág. 91).

En el mismo sentido Zabaljáuregui, clasifica las interrupciones de contexto de la


siguiente forma:

 “Los manejadores de interrupciones no se ejecutan en el contexto de 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”
(Zabaljáuregui, 2008, pág. 9).

Los autores Daniel Bovet y Marco Cesati aparir de los contextos de ejecución del
kernel señalan que “se puede generalizar que cada procesador de una máquina
está haciendo alguna de estas tres cosas en un momento dado:”

 “En kernel pace, 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” (Deitel, 1993,
pág. 97).

Kernel Threads

De acuerdo con el autor Francisco González, “Los Kernel Threads corren en


kernel space, no necesitan tablas de página para mapear memoria de usuario,
además no interactúan con usuarios, por lo que no requieren dispositivos de E/S
(terminales) y por lo tanto Contexto más liviano, por lo tanto, el switch es más
rápido que el de un proceso de usuario” (González, 2004, pág. 11).

Funciones Diferibles

De acuerdo con el autor Francisco González, “El manejador de interrupciones no


es un contexto en el que puedan realizarse cualquier tipo de acción. Por ejemplo,
no debe bloquearse nunca. Además, 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” (González,
2004, pág. 12).

El kernel de Linux implementa esto usando dos tipos de funciones diferibles


(“bottom halves”) del kernel: “softirqs” y “tasklets” (Deitel, 1993, pág. 101).

Contextos de Ejecución del  Kernel (Completo)

Francisco González señala que ,“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 y finalmente una softirq es ejecutada” (González, 2004,
pág. 13).

Ejemplo de ejecución
Ilustración 10: Ejemplo de Ejecución Kernel Linux. Fuente: Introducción al kernel Linux (González,
2004).

NOTA: Este núcleo gestiona recursos mediante servicios de llamada al sistema operativo y decide
cuáles son los programas que harán uso de un dispositivo de hardware y cuál será su duración,
distribuyendo los recursos de la mejor forma, para que los componentes externos e internos del
ordenador puedan trabajar en conjunto. Otra de sus funciones, es la de administrar la memoria de
los procesos y programas en ejecución.

Estructura del Kernel (Linux)

Ilustración 11: Estructura del Núcleo. Fuente: El Kernel (Méndez, 2019).

NOTA: Las System Calls son funciones que permiten a los procesos de usuario pedirle al kernel
que realice operaciones en su nombre. Una System Call es cualquier función que el kernel expone
que puede ser utilizada por un proceso a nivel usuario.

Timer Interrupts (Interrupciones por temporizador)

De acuerdo con el autor Mariano Méndez, “Para que el kernel pueda tomar el
control de la computadora debe haber algún mecanismo que periódicamente le
permita al kernel desalojar al proceso de usuario en ejecución y volver a tomar el
control del procesador, y así de toda la máquina. Por otro lado, Cuando una
interrupción por tiempo ocurre, el proceso en modo usuario que se esté
ejecutando le transfiere el control al kernel ejecutándose en modo kernel. De esta
forma el kernel tiene asegurado el uso del procesador” (Méndez, 2019, pág. 4).

“Cuando un programa se está ejecutando este cree que tiene todo el tiempo del
mundo para hacer lo que quiera, pero eso es sólo una ilusión, son controlados por
Timer Interrupts” (Silverchatz, 2006, pág. 155).

Linux: monolítico moderno

De acuerdo con el autor Matías Zabaljáuregui, “El kernel de Linux es monolítico,


sin embargo, toma muchas de las buenas ideas de los microkernels:”

 Diseño modular
 Scheduleable / preemptible (KCPs)
 Soporte para kernel threads
 Módulos Dinámicos en demanda” (Zabaljáuregui, 2008 , pág. 38).

Reentrancia

Según el autor Matías Zabaljáuregui, “La Reentrancia del núcleo de Linux funciona
de la siguiente manera”:

 “Todos los kernels Linux 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 sus
pender 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 h
acen algunos kernels de tiempo real),  aunque esto no es siempre posible.
 Otra forma es permitir funciones no reentrantes y utilizar mecanismos de
locking” (Zabaljáuregui, 2008, pág. 22).
“Linux es un kernel reentrante. Esto significa que más de un proceso puede estar
ejecutándose en modo kernel al mismo tiempo. Por supuesto, en sistemas
monoprocesador, sólo un proceso puede progresar, pero el resto puede estar
bloqueado en modo kernel esperando por la CPU o que se complete alguna
operación de E/S. Si ocurre una interrupción de hardware (explicada más abajo),
un kernel reentrante es capaz de suspender el proceso actual, incluso si este
proceso está ejecutándose en modo kernel. Esta capacidad es muy importante, ya
que mejora el rendimiento de los controladores de dispositivos (pues una vez que
un dispositivo ha activado su señal de interrupción, se queda esperando a que la
CPU la confirme)” (Hernández, 2002, pág. 23).

Semáforos

De acuerdo con el autor Matías Zabaljáuregui, “Linux ofrece dos tipos de


semáforos, aunque en este informe interesan sólo los primeros:”

 “Semáforos del kernel, usados por los KCP.


 Semáforos “System V IPC”, usados por los procesos en modo usuario”
(Zabaljáuregui, 2005, pág. 12).

“Cuando un KCP intenta obtener un recurso ocupado protegido por un semáforo


del kernel, el proceso correspondiente es suspendido. El proceso volverá al estado
RUNNABLE cuando el recurso sea liberado” (Silverchatz, 2006, pág. 163).

Zabaljáuregui también agrega que, “Un semáforo del kernel es un objeto de tipo
struct semaphore, conteniendo los campos mostrados en la siguiente lista:”

 “count: Almacena un contador atomic_t. Si es mayor que 0, entonces el


recurso está libre. Si es igual a 0, el recurso está ocupado pero ningún otro
proceso está esperando. Finalmente, si count es negativo, el recurso no está
disponible y al menos un proceso está esperando para usarlo.
 Wait: Almacena la dirección de una cola de espera (wait queue) que incluye a
todos los procesos dormidos que están esperando por el recurso. Si count es
mayor o igual a 0, la cola está vacía.
 Sleepers: Guarda un flag que indica si algún proceso está bloqueado en el
semáforo” (Zabaljáuregui, 2008, pág. 14).
“Las macros init_MUTEX e init_MUTEX_LOCKED pueden ser utilizadas para
inicializar un semaforo para acceso exclusivo: setean el campo count a 1(recurso
libre) y 0 (recurso no disponible con acceso exclusivo cedido al proceso que
inicializa el semaforo) respectivamente. Un semáforo podría se inicializado con
cualquier valor positivo en count para permitir el acceso concurrente de más de un
proceso al recurso. Cuando un proceso desea liberar un semáforo, invoca la
función up( ). Por el contrario, cuando un proceso desea acceder a un recurso
protegido, invoca a la función down( )” (Deitel, 1993, pág. 167).

Según el autor, Galvin Silverchatz, “sólo manejadores de excepciones y algunas


rutinas de servicio de llamadas al sistema pueden usar la función down( ). Los
manejadores de interrupciones o funciones diferibles no deben invocar down ( ) ya
que esta función suspende al proceso cuando el semáforo está ocupado. Por esta
razón, linux ofrece la función down_trylock () que puede ser utilizada sin
problemas por las funciones asincrónicas mencionadas anteriormente. Esta
función es idéntica a down ( ) excepto que cuando el recurso está ocupado, la
función retorna inmediatamente en lugar de poner al proceso a dormir”
(Silverchatz, 2006, pág. 169).

Arquitectura de máquina virtual

“El núcleo Linux puede correr sobre muchas arquitecturas de máquina virtual,
tanto como host del sistema operativo o como cliente. La máquina virtual
usualmente emula la familia de procesadores Intel x86, aunque en algunos casos
también son emulados procesadores de PowerPC o AMD” (Lovk, 2010, pág. 47).

Semáforos de Lectura/Escritura

“Estos semáforos son una característica aparecida en la versión 2.4 de Linux. Son
similares a los spinlocks de Lectura/Escritura, excepto que los procesos que
esperan son suspendidos hasta que el recurso se libera” (Zabaljáuregui,
2005,pág. 13).

Robert Lovk señala además que, “El kernel maneja a los procesos en un orden
FIFO. Cada lector o escritor que encuentra el semáforo bloqueado es agregado en
la última posición de la cola de espera del semáforo. Cuando este es liberado, el
proceso en la primera posición de la wait que list es despertado y chequeado. Si
es un escritor, el resto de los procesos continúan durmiendo. Si es un lector, el
resto de los lectores que le sigan en la lista serán despertados y tomarán el
semáforo, hasta encontrar un escritor, Un semáforo de lectura/escritura es
modelado con una estructura rw_semaphore que incluye los siguientes campos:”

 “count: son dos contadores de 16 bits. El contador en la palabra más


significativa almacena en complemento a 2 el número de KCPs que esperan.
El otro contador almacena el número total de escritores y lectores en el
recurso.
 wait_list: Apunta a una lista de procesos esperando. Cada elemento en la lista
es una estructura rwsem_waiter, incluyendo un puntero al descriptor del
proceso que espera y un flag indicando si el proceso quiere leer o escribir.
 wait_lock: Un spin lock utilizado para proteger la cola de espera y a la
estructura rw_semaphore” (Lovk, 2010, pág. 65).

Deshabilitación local de interrupciones

De acuerdo con el autor Matías Zabaljáuregui, “Deshabitar las interrupciones es


uno de los mecanismos clave utilizado para asegurar que una secuencia de
sentencias del kernel es tratada como una sección crítica. Permite que un KCP
continue su ejecución aun cuando un dispositivo de hardware active una señal de
interrupción y de esta forma provee una manera efectiva de proteger estructuras
de datos que también son accedidas por manejadores de interrupciones. Sin
embargo, en sistemas multiprocesador, la Deshabilitación de interrupciones
locales no protege contra accesos concurrentes de manejadores de interrupciones
que se ejecuten en otras CPUs. Es por eso por lo que suelen combinarse con
spinlocks” (Zabaljáuregui, 2008, pág. 21).

“La instrucción asembler cli, pone a cero el flag IF del registro eflags para
deshabilitar las interrupciones, pero al final de la sección crítica no se puede
simplemente setear el flag nuevamente. Esto es así porque los manejadores de
interrupciones (de interrupciones diferentes) pueden ejecutarse de manera
anidada, por lo tanto, el kernel no conoce necesariamente cual era el valor del flag
IF antes de que se ejecutara el KCP actual. En estos casos, se debe guardar el
valor anterior y luego restaurarlo a su valor original” (Silverchatz, 2006, pág. 72).

Deshabilitación global de interrupciones

“La deshabilitación global de interrupciones se realiza mediante la macro cli( ). En


sistemas monoprocesadores, esta macro simplemente se expande a __cli( ),
deshabilitando las interrupciones locales. En sistemas multiprocesador, la macro
espera hasta que terminen todos los manejadores de interrupciones y funciones
diferibles, y luego toma un spin lock especial llamado global_irq_lock”
(Zabaljáuregui, 2008, pág. 29).

Funciones Diferibles: “Softirqs”, “Tasklets”, y “Bottom Halves”

“Linux implementa esto usando tres tipos de funciones diferibles del kernel:
“softirqs”, “tasklets” y “bottom halves”. Aunque estos tipos de funciones se
implementan de manera diferente, están muy relacionadas. De hecho, el término
“softirq”, que aparece en el código fuente, usualmente denota todos los tipos de
funciones diferibles y en la sección 3 del informe, este término se usará de esa
forma” (Zabaljáuregui, 2005, pág. 37).

De acuerdo con el autor Manuel Hernández, “Como regla general, una softirq no
puede ser interrumpida para ejecutar otra softirq en la misma CPU. Lo mismo
sucede con las otras funciones diferibles. Sin embargo, en un sistema
multiprocesador, varias funciones diferibles pueden ejecutarse concurrentemente
en diferentes CPUs. El grado de concurrencia depende del tipo de función:”

 “Las softirq son reentrantes, es decir, pueden ejecutarse en varias CPUs


concurrentemente, incluso si son del mismo tipo.
 Las tasklets de diferentes tipos pueden ejecutarse concurrentemente, pero las
del mismo tipo no.
 Las bottom halves son globalmente serializadas; cuando una se está
ejecutando en alguna CPU, ninguna otra lo estará haciendo en otra CPU.
Esta es una gran limitación de Linux para sistemas multiprocesador, y de
hecho, las bottom halves sólo se mantienen por cuestiones de compatibilidad.
(Se espera que los desarrolladores de drivers se actualicen reemplazando las
bottom halves por tasklets, y que las bottom halves desaparezcan del
kernel.)” (Hernández, 2002, pág. 53).

El investigador Alberto Lafuente agrega que, “la multiplexación se completa


reestableciendo el estado del procesador para que ejecute el proceso planificado,
esto implica hacer que el SP apunte a la pila del nuevo proceso. La rutina
restaurar(), codificada en ensamblador, es la que se encarga de ello, manipulando
el bloque de activación anterior. Previamente, la rutina salvar_reg() habrá salvado
el estado del proceso que estaba en ejecución” (Lafuente, 2006, pág. 9).

Igualmente señala que, “La gestión del tiempo compartido la realiza la rutina de
atención al reloj, multiplexar(), esta rutina incluye otras funciones (apagado
automático del motor de la unidad de disco y control del periodo transitorio tras el
encendido, retardo de procesos por tiempo)” (Lafuente, 2006, pág. 9).

Ilustración 12: Rutina multiplexar. Control de quantum. Fuente: Laboratorio de Sistemas Operativos
(UPV/EHU ATC, 2006).

NOTA: Los segmentos del espacio de direcciones que son visibles desde el código son el de
código, datos y pila. Cuando ocurre una interrupción el procesador pasa al modo sistema e invoca
una rutina de atención de esa interrupción. Esta rutina es provista por el núcleo y su dirección se
rescata del vector de interrupciones, el que no es visible desde un proceso en modo usuario.
Creación, control y destrucción de procesos

De acuerdo con el autor Alberto Lafuente, “La rutina crear_pcb_nuc() asigna un


PCB para un nuevo proceso, provocando la expulsión del que está en ejecución.
Existen primitivas para extraer información de un proceso y su identificador
(info_proc_nuc(), quisoc_nuc()) y para modificar su quantum y prioridad
(modif_proc_nuc())” (Lafuente, 2006, pág. 10).

Rutinas de tratamiento de interrupciones

Alberto Lafuente sostiene que, “Aunque la rutina multiplexar puede servir como
ejemplo de rutina de tratamiento de interrupciones, resultará clarificador en este
momento introducir el código de la rutina de tratamiento de las interrupciones de
teclado” (Lafuente, 2006, pág. 11).

Ilustración 13: Rutina de tratamiento de interrupciones. Control de quantum. Fuente: Laboratorio de


Sistemas Operativos (UPV/EHU ATC, 2006).

NOTA: Cuando ocurre una interrupción, el procesador busca si las interrupciones están
enmascaradas. Si es así, no pasa nada hasta que se desenmascaran. Cuando las interrupciones
se desenmascaran, si hay interrupciones pendientes, el procesador elige una.

Primitivas no bloqueantes
Igualmente, Alberto Lafuente comparte que, “Son aquellas que no dejan al
proceso bloqueado, serán de este tipo aquellas primitivas que no se sirven
mediante interrupciones, como es el caso de esribir_pantalla_nuc(),
scroll_nuc(),generalmente estas primitivas se resuelven como simples llamadas a
funciones y no producen cambios de contexto” (Lafuente, 2006, pág. 12).

Ilustración 14: Rutina no bloqueante. Fuente: Laboratorio de Sistemas Operativos (UPV/EHU ATC,
2006).

NOTA: El proceso se está ejecutando porque no se han producido ciertos eventos esperados,
como la falta de solicitud de recursos del sistema, la espera de la finalización de una determinada
operación, la llegada de nuevos datos o la falta de trabajo nuevo, etc. El sistema ejecuta
automáticamente la primitiva de bloqueo (Bloqueo) para cambiar del estado de ejecución al estado
de bloqueo. Se puede ver que el bloqueo del proceso es un comportamiento activo del proceso en
sí mismo y, por lo tanto, solo el proceso en el estado de ejecución (obtención de la CPU) puede
convertirlo en un estado de bloqueo .Cuando el proceso entra en estado de bloqueo, no ocupa
recursos de la CPU。

Sincronización entre procesos


Alberto Lafuente ratifica que, “El núcleo propuesto ofrece semáforos como
mecanismo básico de sincronización entre procesos. Un semáforo se identifica por
un entero. Se introduce una nueva condición de bloqueo para los procesos, con
tantas colas como semáforos disponibles, NSEM. El bloqueo por semáforo
presenta la particularidad de que debe seguir estrictamente una disciplina FCFS,
por lo que el mecanismo de bloqueo estándar introducido para las rutinas
bloqueantes no se puede aplicar en la primitiva de espera por semáforo,
wait_nuc()” (Lafuente, 2006, pág. 13).
Ilustración 15: Rutina wait_nuc. Fuente: Laboratorio de Sistemas Operativos (UPV/EHU ATC,
2006).

NOTA: Es la situación donde varios procesos acceden y manejan datos compartidos


concurrentemente. El valor final de los datos compartidos depende de qué proceso termina último.
Para prevenir las condiciones de carrera, los procesos concurrentes cooperativos deben ser
sincronizados.

Puesta en marcha

De acuerdo con el autor Alberto Lafuente refiere, “Al no disponer de un sistema


operativo completo con todas sus herramientas para soportar aplicaciones, de
este modo el funcionamiento del núcleo con un conjunto de programas de prueba
que usan las primitivas. En cualquier caso, se requiere un programa que instale el
núcleo y lance los procesos del sistema. Este programa incluirá:”

 El código completo del núcleo, que incluye primitivas, rutinas internas y


librerías de bajo nivel.
 El código de la prueba del núcleo, que es un conjunto de funciones en código
C que se ejecutarán asíncronamente, como threads o procesos a ser
gestionados por el núcleo.
 El procedimiento principal (main) de puesta en marcha.
 Instalación de las rutinas de tratamiento de interrupciones, mediante
vector_int().
 Inicialización de las colas del núcleo (run, ready, teclado, semáforos, …).
 Inicialización de los PCBs como libres, encolándolos en la cola de libres.
 Creación de los procesos del sistema. Al menos son necesarios dos: el
proceso nulo, y un proceso de inicialización, que lanzará el resto ya sobre el
núcleo. Estos procesos se crean rellenando directamente los campos de los
PCBs y utilizando la rutina crear_pcb() para asignar la pila correspondiente y
apuntar al código del proceso.
 Planificar (dispatcher y scheduler) y cargar el estado del proceso
seleccionado (mediante restaurar()). Este proceso será el de inicialización, ya
que el nulo se habrá creado con la prioridad mínima (Lafuente, 2006, pág.
13).

Prueba del núcleo

Alberto Lafuente señala que, “Los ficheros fuente del núcleo que se proporcionan
son:”

 rutinas.h Definiciones fundamentales del núcleo; declaraciones de rutinas


auxiliares y de manejo de colas, y declaraciones de rutinas ensamblador y C
dependientes del hardware.
 maquina.h Definiciones (condicionales) dependientes de la pantalla y el
teclado.
 nucleo.h Primitivas del núcleo” (Lafuente, 2006, pág. 15).

Ejecución

El autor Alberto Lafuente refiere que “una vez compilado y montado el código, se
puede probar el funcionamiento del núcleo con ayuda del código ejecutable
obtenido. Al ejecutar fase0 se ofrecen mediante un menú las pruebas de
diferentes aspectos del núcleo:”

 “Control de procesos. Permite manejar prioridades y quanta de procesos.


 Control del disco flexible. Permite operar el motor, posicionar el cabezal y
transferir información entre disco y memoria” (Lafuente, 2006, pág. 15).
Ilustración 16: : Rutinas y librerías LOW LEVEL. Fuente: Laboratorio de Sistemas Operativos
(UPV/EHU ATC, 2006).

NOTA: Las llamadas al sistema siempre las ejecuta el núcleo en el modo sistema. La única forma
de pasar desde una aplicación al modo sistema es por medio de una interrupción. Por lo tanto, las
llamadas al sistema se implementan precisamente a través de una interrupción.

Referencias
Aleman, Ó. (2002). El movimiento del software libre. Recuperado el 21 de 09 de
2022, de Redalyc: [Link]
Bovet, D., & Cesati, M. (2006). Understanding the LINUX KERNEL. United States
of America: O’Reilly. Recuperado el 25 de 09 de 2022, de
[Link]
Castillo, H. (2011). Estructura del Kernel Linux. Recuperado el 21 de 09 de 2022,
de Operative Sistems UNS:
[Link]
Deitel, M. (1993). Sistemas operativos (Segunda ed.). México: Addison-Wesley
Iberoamericana. Recuperado el 21 de 09 de 2022
González, F. (2004). Módulo 9: Núcleo de Linux. Recuperado el 21 de 09 de 2022,
de Sistemas Operativos – Redes y Telecomunicaciones – I.T.U.:
[Link]
Hernández, M. (2002). Mecanismos de Sincronización Núcleo Linux. Arquitectura
del Kernel. Malaga. Recuperado el 25 de 09 de 2022, de
[Link]
[Link]
Lafuente, A. (Febrero de 2006). Departamento de Arquitectura y Tecnología de
Computadores. Núcleo de un Sistema Operativo. Recuperado el 21 de 09
de 2022, de [Link]
Lovk, R. (2010). Linux Kernel Development (Third Edition ed.). United States of
America: Addison-Wesley. Recuperado el 25 de 09 de 2022, de
[Link]
cours-&-manuels-informatiques/Linux/Linux%20Kernel%20Development,
%203rd%[Link]
Méndez, M. (2019). El Kernel. Recuperado el 25 de 09 de 2022, de Sisop:
[Link]
Peña, J. (2006). El Sistema Operativo LINUX y el cambio necesario. Recuperado
el 21 de 09 de 2022, de Redalyc:
[Link]
Pinchon, P. (2009). Administración avanzada - Mantenimiento y explotación de los
servidores Linux. Recuperado el 25 de 09 de 2022, de ENI:
[Link]
idR=f64083831dd277588b94b85f3a293242
Silverchatz, G. (2006). Fundamentos de Sistemas Operativos (Séptima ed.).
España: McGraw-Hill. Recuperado el 21 de 09 de 2022
Solorzano, S. (10 de 2009). GNU/LINUX WITHIN THE FRAMEWORK OF
SOCIAL. Recuperado el 21 de 09 de 2022, de Redalyc:
[Link]
Vázquez, A. (2004). Núcleo Linux. Aspectos técnicos estructura del Kernel.
España. Recuperado el 25 de 09 de 2022, de
[Link]
Zabaljáuregui, M. (2005). Concurrencia y mecanismos de sincronización en el
kernel Linux. España. Recuperado el 25 de 09 de 2022, de
[Link]
[Link]
Zabaljáuregui, M. (2008). Introducción al kernel Linux. España. Recuperado el 22
de 09 de 2022, de [Link]
[Link]

También podría gustarte