Arquitectura del Kernel Linux

27
ARQUITECTURA DEL KERNEL LINUX Néstor Julián Molina Osorio e-mail: [email protected] Carlos Andrés Flórez Villarraga e-mail: [email protected] RESUMEN: El kernel de Linux es el núcleo de un sistema operativo grande y complejo, y aunque es enorme, está bien organizado en términos de subsistemas y capas. En este artículo, vamos a explorar la estructura general del núcleo de Linux y conocer sus principales subsistemas y las interfaces básicas, además hablaremos un poco de las funciones principales del núcleo como asignación de memoria, administración de los dispositivos hardware. PALABRAS CLAVE: Kernel, Linux, Sistema Operativo INTRODUCCIÓN Los sistemas operativos no sólo son considerados como una parte fascinante de la tecnología de información, pero son también objeto de debate polémico entre el público. Linux ha desempeñado un papel importante en este desarrollo, mientras que hace sólo 10 años una estricta distinción fue hecha entre relativamente simples sistemas académicos disponibles en código fuente y las variantes comerciales con distintos resultados, cuyas fuentes eran un secreto bien guardado, hoy en día cualquiera puede descargar las fuentes de Linux (o de cualquier otro sistema libre de otro tipo) a través de Internet con el fin de estudiarlos. Linux ya está instalado en millones de sistemas y es utilizado por usuarios domésticos y profesionales para una amplia gama de tareas. Desde miniatura sistemas empotrados en los relojes de pulsera hasta el paralelo de forma masiva mainframes, hay incontables maneras de explotar a Linux de manera productiva. Y esto hace que las fuentes tan interesantes. Un sonido, concepto bien establecido (Unix) se fundió con las innovaciones de gran alcance y una tendencia fuerte para hacer frente a problemas que no se producen en los sistemas de enseñanza académica es lo que hace que Linux sea tan fascinante. El presente trabajo una visión general de las distintas áreas del Kernel y de ilustrar a los sus relaciones fundamentales. Dado que el Kernel se desarrolla rápidamente, una pregunta que naturalmente viene a la mente es la versión que se está cubriendo en este trabajo. Se ha elegido el kernel 2.6.24, que fue lanzado a finales de enero de 2008. La naturaleza dinámica de desarrollo del kernel implica que una nueva versión del kernel estará disponible, por el momento estudiamos la versión nombrada anteriormente. 1. UN PEQUEÑO PASEO POR LA HISTORIA DE LINUX Aunque Linux es sin duda el sistema de código abierto más popular de funcionamiento, su historia es bastante corta teniendo en cuenta la cronología de los sistemas operativos. En los primeros días de la computación, los programadores desarrollaron un Lenguaje Maquina sobre el Hardware, el cual permitía administrarlo. La falta de un sistema operativo significa que sólo una aplicación (y un usuario) podría utilizar el dispositivo, y eso era un inconveniente ya que estas maquinas eran muy costosas y además solo realizaban una función. Los primeros sistemas operativos fueron desarrollados en la década de 1950 para proporcionar una experiencia de desarrollo más simple. Los ejemplos incluyen el sistema operativo de General Motors (OMG) desarrollado para el IBM 701 y el FORTRAN Monitor System (FMS), desarrollado por North American Aviation para la IBM 709.

description

En este paper se tratan distintos aspectos de la arquitectura del kernel linux

Transcript of Arquitectura del Kernel Linux

Page 1: Arquitectura del Kernel Linux

ARQUITECTURA DEL KERNEL LINUX

Néstor Julián Molina Osorio e-mail: [email protected]

Carlos Andrés Flórez Villarraga

e-mail: [email protected]

RESUMEN: El kernel de Linux es el núcleo de

un sistema operativo grande y complejo, y aunque

es enorme, está bien organizado en términos de

subsistemas y capas. En este artículo, vamos a

explorar la estructura general del núcleo de Linux

y conocer sus principales subsistemas y las

interfaces básicas, además hablaremos un poco

de las funciones principales del núcleo como

asignación de memoria, administración de los

dispositivos hardware.

PALABRAS CLAVE: Kernel, Linux, Sistema

Operativo

INTRODUCCIÓN

Los sistemas operativos no sólo son considerados

como una parte fascinante de la tecnología de

información, pero son también objeto de debate

polémico entre el público. Linux ha desempeñado

un papel importante en este desarrollo, mientras

que hace sólo 10 años una estricta distinción fue

hecha entre relativamente simples sistemas

académicos disponibles en código fuente y las

variantes comerciales con distintos resultados,

cuyas fuentes eran un secreto bien guardado, hoy

en día cualquiera puede descargar las fuentes de

Linux (o de cualquier otro sistema libre de otro

tipo) a través de Internet con el fin de estudiarlos.

Linux ya está instalado en millones de sistemas y

es utilizado por usuarios domésticos y

profesionales para una amplia gama de tareas.

Desde miniatura sistemas empotrados en los

relojes de pulsera hasta el paralelo de forma

masiva mainframes, hay incontables maneras de

explotar a Linux de manera productiva. Y esto

hace que las fuentes tan interesantes. Un sonido,

concepto bien establecido (Unix) se fundió con las

innovaciones de gran alcance y una tendencia

fuerte para hacer frente a problemas que no se

producen en los sistemas de enseñanza

académica es lo que hace que Linux sea tan

fascinante.

El presente trabajo una visión general de las

distintas áreas del Kernel y de ilustrar a los sus

relaciones fundamentales.

Dado que el Kernel se desarrolla rápidamente,

una pregunta que naturalmente viene a la mente

es la versión que se está cubriendo en este

trabajo. Se ha elegido el kernel 2.6.24, que fue

lanzado a finales de enero de 2008. La naturaleza

dinámica de desarrollo del kernel implica que una

nueva versión del kernel estará disponible, por el

momento estudiamos la versión nombrada

anteriormente.

1. UN PEQUEÑO PASEO POR LA

HISTORIA DE LINUX

Aunque Linux es sin duda el sistema de código

abierto más popular de funcionamiento, su historia

es bastante corta teniendo en cuenta la cronología

de los sistemas operativos. En los primeros días

de la computación, los programadores

desarrollaron un Lenguaje Maquina sobre el

Hardware, el cual permitía administrarlo. La falta

de un sistema operativo significa que sólo una

aplicación (y un usuario) podría utilizar el

dispositivo, y eso era un inconveniente ya que

estas maquinas eran muy costosas y además solo

realizaban una función. Los primeros sistemas

operativos fueron desarrollados en la década de

1950 para proporcionar una experiencia de

desarrollo más simple. Los ejemplos incluyen el

sistema operativo de General Motors (OMG)

desarrollado para el IBM 701 y el FORTRAN

Monitor System (FMS), desarrollado por North

American Aviation para la IBM 709.

Page 2: Arquitectura del Kernel Linux

En la década de 1960, Massachusetts Institute of

Technology (MIT) y una serie de empresas

desarrollaron un sistema operativo experimental

llamado Multics (Servicio de Información y

Computación multiplexados) para el GE-645. Uno

de los desarrolladores de este sistema operativo,

AT & T, se retiró de Multics y desarrollado su

propio sistema operativo en 1970 llamado unics.

Junto con este sistema operativo era el lenguaje

C, para lo cual se desarrolló C y luego reescrito

para que el desarrollo del sistema operativo

portátil.

Veinte años más tarde, Andrew Tanenbaum creó

una versión microkernel de UNIX ®, llamado

MINIX (por mínima UNIX), que corría en pequeños

computadores personales. Este Sistema Operativo

de código abierto fue la inspiración para que

inicialmente Linus Torvalds creara Linux a

principios de 1990. En la siguiente figura se puede

observar el número de líneas por las que está

compuesto el código fuente del Kernel de Linux a

través de su historia.

Linux evolucionó rápidamente de un proyecto de

una sola persona a un proyecto de desarrollo en

todo el mundo con miles de desarrolladores. Una

de las decisiones más importantes de Linux fue la

aprobación de la GNU General Public License

(GPL). Bajo la GPL, el núcleo Linux fue protegido

contra la explotación comercial, y se contó

también con el desarrollo del espacio de usuario

del proyecto GNU (de Richard Stallman). Esto

permitió utilizar aplicaciones útiles, como el GNU

Compiler Collection (GCC) y diferentes soportes

de shell.

2. INTRODUCCIÓN AL KERNEL DE LINUX

Ahora en un aspecto general en la arquitectura del núcleo GNU / Linux, Podemos pensar en un sistema operativo a partir de dos niveles, como se muestra en la Figura0. Más adelante en la sección Elementos de Núcleo se profundizará un poco en todos los componentes del núcleo de Linux.

2.1 ARQUITECTURA FUNDAMENTAL DEL SISTEMA OPERATIVO GNU / LINUX

Figura0

En la parte superior es el espacio del usuario, o la

aplicación. Aquí es donde las aplicaciones de

usuario se ejecutan. Debajo del espacio del

usuario se encuentra el espacio del núcleo. En

este caso, el núcleo de Linux existe(es real).

También está la Librería C de GNU (glibc). Esto

proporciona a la SCI una conexión con el núcleo y

proporciona el mecanismo para la transición entre

la aplicación del espacio del usuario y el kernel.

Esto es importante porque el núcleo y la aplicación

de usuario ocupan diferentes espacios de

direcciones protegidas. Y si bien cada proceso en

espacio de usuario ocupa su propio espacio de

direcciones virtuales, el núcleo ocupa un espacio

de dirección única.

El kernel de Linux se puede dividir en tres grandes

niveles. En la parte superior es la SCI, que ejecuta

las funciones básicas tales como leer y escribir.

Por debajo de la SCI es el código del núcleo, que

puede definirse con mayor precisión como el

Page 3: Arquitectura del Kernel Linux

código del núcleo de la arquitectura (actualmente

el código tiene más de diez millones de líneas).

Este código es común a todas las arquitecturas de

procesadores soportados por Linux. Por debajo de

este es el código dependiente de la arquitectura,

que forma lo que se conoce más comúnmente

como un BSP (Board Support Package). Este

código sirve como el procesador y el código

específico de plataforma para la arquitectura

determinada.

Métodos para la interfaz de llamada al sistema (SCI)

En realidad, la arquitectura no es tan limpia como lo que se muestra en la Figura 0. Por ejemplo, el mecanismo por el cual se manejan las llamadas al sistema (la transición desde el espacio de usuario al espacio del núcleo) puede diferir por la arquitectura. Las nuevas unidades de procesamiento central (CPU) 86 que proporcionan soporte para instrucciones de virtualización son más eficientes en este proceso que la mayoría de CPU que usan procesadores x86, ya que estos utilizan el método tradicional: la int 80h.

2.2 PROPIEDADES DEL KERNEL DE

LINUX

Cuando la arquitectura es de una discusión amplia

y compleja, puede ver el sistema desde muchas

perspectivas. Uno de los objetivos de una

descomposición de la arquitectura es proporcionar

una manera de entender mejor el origen, y eso es

lo que vamos a hacer a continuación.

El kernel de Linux se ha implementado una serie

de importantes atributos arquitectónicos. En un

nivel alto, y en los niveles inferiores, el núcleo se

acoda en una serie de subsistemas distintos.

Linux también puede considerarse monolítica

porque mezcla todos los servicios básicos en el

núcleo. Esto difiere de una arquitectura

microkernel donde el núcleo proporciona servicios

básicos como la comunicación, E / S, la gestión

de memoria y de procesos, y otros servicios más

específicos.

Con el tiempo, el núcleo de Linux se ha convertido

en eficiente en términos de uso de memoria y

CPU, así como una gran estabilidad. Pero el

aspecto más interesante de Linux, dado su

tamaño y complejidad, es su portabilidad. Linux

puede ser compilado para correr en un gran

número de procesadores y plataformas con

diferentes restricciones arquitectónicas y

necesidades. Un ejemplo es la capacidad de Linux

para ejecutar en un proceso con una unidad de

gestión de memoria (MMU), así como los que

proporcionan sin MMU. El puerto uClinux del

kernel de Linux proporciona una ayuda no MMU.

2.3 PRINCIPALES SUBSISTEMAS DEL KERNEL DE LINUX

A continuación se entrará a revisar un poco los principales componentes del núcleo Linux, definiremos estos componentes y explicaremos cual es la función de cada uno. Figura 0.1. Una perspectiva arquitectónica del kernel de Linux

Sistema de interfaz de llamada (SCI)

El SCI es una fina capa que proporciona los

medios para realizar llamadas a funciones desde

el espacio de usuario en el núcleo. Como se ha

dicho, esta interfaz puede ser dependiente de la

arquitectura, incluso dentro de la misma familia de

procesadores. El SCI es en realidad un

interesante servicio de función de guardia de

multiplexación y demultiplexación.

Page 4: Arquitectura del Kernel Linux

La gestión de procesos (PM)

La gestión del proceso se centra en la ejecución

de procesos. En el núcleo, estos son llamados de

hilos y representan un individuo de virtualización

del procesador (código de hilo, datos, pila y

registros de la CPU). En el espacio de usuario, el

término proceso se suele utilizar, aunque la

implementación de Linux no separa los dos

conceptos (procesos y subprocesos). El núcleo

proporciona una interfaz de programación de

aplicaciones (API) a través del SCI para crear un

nuevo proceso (tenedor, exec, o Portable

Operating System Interface [Funciones POSIX]),

detener un proceso (matar, salida) y para

comunicarse y sincronizarse entre ellos (señal, o

mecanismos POSIX).

En la gestión de procesos También necesario

compartir la CPU entre los hilos activos. El núcleo

implementa un algoritmo de programación

novedosa que opera en tiempo constante,

independientemente del número de hilos que

compiten por la CPU. Esto se llama el planificador

O (1), indica que para programar un hilo se usa la

misma cantidad de tiempo. La O (1) planificador

también es compatible con múltiples procesadores

(llamado multiprocesamiento simétrico o SMP).

Gestión de la memoria (MM)

Otro importante recurso que es administrado por

el núcleo es la memoria. Por eficiencia, dada la

forma en que el hardware gestiona la memoria

virtual, la memoria se gestiona en las llamadas

páginas (4 KB de tamaño para la mayoría de las

arquitecturas). Linux incluye los medios para

gestionar la memoria disponible, así como los

mecanismos de hardware para las asignaciones

físicas y virtuales.

Sistema de archivos virtual (VFS)

El sistema de archivos virtual (VFS) es un aspecto

interesante del kernel de Linux, ya que

proporciona una abstracción de interfaz común de

sistemas de archivos. El VFS proporciona una

capa de conmutación entre el SCI y los sistemas

de ficheros soportados por el núcleo (ver Figura

0.2).

Figura 0.2. La VFS ofrece una matriz de

conmutación entre los usuarios y los sistemas de

archivos

En la parte superior de la VFS es una abstracción

común API de funciones tales como abrir, cerrar,

leer y escribir. En la parte inferior de la VFS son

las abstracciones del sistema de archivos que

definen el funcionamiento de la capa superior.

Estos son los plug-ins para el sistema de archivo

dado (de los cuales existen más de 50).

Por debajo de la capa de sistema de archivos está

la caché del búfer, lo que proporciona un conjunto

común de funciones a la capa de sistema de

archivos (independiente de cualquier sistema de

archivos en particular). Esta capa de

almacenamiento en caché optimiza el acceso a los

dispositivos físicos ya que conserva por un

¿Qué es un kernel?

Como se muestra en la figura 0.1, un

núcleo es realmente más que un

administrador de recursos. Si el recurso se

está manejando es un proceso, la

memoria o dispositivo de hardware, el

kernel gestiona y arbitra el acceso a los

recursos entre múltiples usuarios

concurrentes (tanto en el núcleo como en

el espacio de usuario).

Page 5: Arquitectura del Kernel Linux

periodo corto de tiempo datos necesarios para

acceder a estos dispositivos (o especulativamente

leer con anticipación para que los datos estén

disponibles cuando sea necesario). Por debajo de

la caché del búfer son los controladores de

dispositivo, que implementan la interfaz del

dispositivo físico determinado.

Pila de red (Network Stack)

La pila de red, por diseño, sigue una arquitectura

en capas y despues el modelo de los mismos

protocolos. Recordemos que el Protocolo de

Internet (IP) es la red principal de protocolo que se

encuentra por debajo del protocolo de transporte

(más comúnmente el Transmission Control

Protocol o TCP). Por encima de TCP es la capa

de sockets, lo que se invoca a través de la SCI.

La capa de sockets es la API estándar para el

subsistema de red y proporciona una interfaz de

usuario para una variedad de protocolos de red.

Desde el acceso a la propiedad intelectual (PDU)

hasta TCP y el User Datagram Protocol (UDP), la

capa de sockets proporciona una forma

estandarizada para gestionar las conexiones y los

datos.

Los controladores de dispositivos (Device

Drivers)

En la gran mayoría del código fuente del kernel de

Linux existen controladores de dispositivos que

hacen que un determinado dispositivo hardware

sea utilizable. El árbol de código fuente de Linux

proporciona un subdirectorio de drivers que se

divide entre los distintos dispositivos que se

admiten, como Bluetooth, I2C, de serie, y así

sucesivamente.

Código dependiente de la arquitectura

Aunque gran parte de Linux es independiente de

la arquitectura sobre la que se ejecuta, hay

elementos que debe considerar en la arquitectura

para que haya un funcionamiento normal además

eficiencia. El subdirectorio / Linux / define la parte

de la arquitectura-dependiente de las fuentes del

kernel en un determinado número de

subdirectorios que son específicos de la

arquitectura (en conjunto forman el BSP). Para un

escritorio típico, se usa el directorio i386. Cada

subdirectorio contiene un número de otros

subdirectorios que se centran en un aspecto

particular del núcleo, como el arranque, el kernel,

gestión de memoria, y otros.

3. FUNCIONES DEL NÚCLEO

En un nivel puramente técnico, el kernel es una

capa intermedia entre el hardware y el software.

Su objetivo es pasar las solicitudes de aplicación

para el hardware y para actuar como un

controlador de bajo nivel para tratar los

dispositivos y componentes del sistema. Sin

embargo, hay otras maneras interesantes de ver

el kernel:

El kernel puede ser considerado como una

máquina mejorada que, a juicio de la solicitud,

por ejemplo, cuando el kernel se dirige a un

disco duro, debe decidir el camino a utilizar

para copiar datos desde el disco a la memoria,

donde los datos residen, que ordena deben ser

enviadas a la disco a través de qué camino, y

así sucesivamente. Las aplicaciones, por el

contrario, sólo necesitan el comando que los

datos han de ser transferidos. ¿Cómo se hace

esto es irrelevante para la aplicación. Los

datos se extraen por el núcleo. Los programas

de aplicación no tienen contacto con el

hardware en sí, sólo con el kernel, que, para

ellos, representa el nivel más bajo en la

jerarquía que saben y por tanto es una

máquina mejorada.

Viendo el kernel como un administrador de

recursos, cuando se ejecutan varios

programas al mismo tiempo en el sistema, el

kernel es una instancia que comparte recursos

disponibles como tiempo de CPU, espacio en

disco, conexiones de red, y así sucesivamente.

El kernel debe garantizar la integridad del

sistema.

Otra vista del Kernel es como una biblioteca

que proporciona una serie de comandos

orientados al sistema. Como es de

conocimiento general, las llamadas al sistema

(system calls) se utilizan para enviar peticiones

al sistema y, con la ayuda de la biblioteca C

estándar, estos parecen los programas de

aplicación como funciones normales que se

Page 6: Arquitectura del Kernel Linux

invocan de la misma manera como cualquier

otra función.

4. ESTRATEGIAS DE

IMPLANTACIÓN

En la actualidad, hay dos principales paradigmas

en que se basa la aplicación de sistemas

operativos:

1. Micro núcleos, sólo las funciones más

elementales son ejecutadas directamente en

un núcleo central. Todas las demás

funciones se delegan a autónomos procesos

que se comunican con el núcleo central a

través de comunicación claramente definidas

interfaces, por ejemplo, sistemas de

archivos distintos, la gestión de memoria, y

así sucesivamente. (Por Por supuesto, el

nivel más elemental de la gestión de

memoria que controla la comunicación con el

sistema en sí está en un micro núcleo. Sin

embargo, la manipulación en el nivel de

llamada del sistema es implementado en

servidores externos.) Teóricamente, éste es

un enfoque muy elegante porque las partes

individuales están claramente separados

unos de otros. Otros beneficios de este

enfoque son extensibilidad dinámica y la

capacidad de intercambiar componentes

importantes en tiempo de ejecución. Sin

embargo, debido al tiempo de CPU

necesarios para apoyar la comunicación

compleja entre los componentes, los micro

núcleos realmente no se han establecido en

la práctica a pesar de que han sido objeto de

investigación activa y variada desde hace

algún tiempo.

2. Núcleos monolíticos, son la alternativa, el

concepto tradicional. En este caso, el código

completo del núcleo que incluye todos los

subsistemas tales como administración de

memoria, sistemas de ficheros, o

controladores de dispositivo se embala en un

solo archivo. Cada función tiene acceso a

todas las demás partes el núcleo, lo que

puede dar lugar a elaboradamente código

fuente anidados si la programación no se

hace con mucho cuidado.

En este momento, el rendimiento de núcleos

monolíticos sigue siendo superior a la de micro

núcleos, Linux era y sigue siendo implementado

de acuerdo a este paradigma. Sin embargo, una

importante innovación ha sido introducida. Los

módulos con el código del kernel que pueden ser

insertados o removidos cuando el sistema está

funcionando y además de apoyar la dinámica de

toda una serie de funciones para el núcleo,

compensando así parte de las desventajas de los

núcleos monolíticos. Este es asistido por medios

de comunicación entre la elaboración el núcleo y

entorno de usuario que permite la aplicación de

conexión en caliente y la carga dinámica de

módulos.

5. ELEMENTOS DEL NÚCLEO

En esta sección se ofrece una reseña de los

diversos elementos del núcleo. A pesar de su

enfoque monolítico, Linux es sorprendentemente

bien estructurado. Sin embargo, es inevitable que

sus elementos interactúan entre sí, sino que

comparten las estructuras de datos, y (por razones

de rendimiento) cooperar entre sí a través de más

funciones que sería necesaria en un sistema

estrictamente segregado.

La Figura 1 proporciona una visión general inicial

sobre las capas que componen un sistema Linux

completo, y también sobre algunos subsistemas

importantes del Kernel como tal. Nótese, sin

embargo, que los subsistemas individuales van a

interactuar en una variedad de formas adicionales

en la práctica que no se muestran en la figura.

Page 7: Arquitectura del Kernel Linux

Figura 1

5.1 PROCESOS DE CONMUTACIÓN

DE TAREAS Y SCHEDULING

Las aplicaciones, servicios y otros programas que

funcionan, bajo Unix se conocen tradicionalmente

como procesos. Cada proceso se asigna espacio

de direcciones virtuales en la memoria de la CPU.

Los espacios de dirección de los procesos son

totalmente independientes, por lo que cada

proceso tiene la impresión de ser el único proceso

en el sistema. Si un proceso desea realizar de

datos, por ejemplo, entonces los mecanismos

especiales del Kernel deben ser utilizados.

Debido a que Linux es un sistema multitarea,

soporta lo que parece ser la ejecución

concurrente de varios procesos. Dado que sólo

tantos procesos como existen CPUs en el sistema

realmente puede funcionar al mismo tiempo, los

modificadores del núcleo (apreciados por los

usuarios) entre los procesos en intervalos cortos

para darles la impresión de procesamiento

simultáneo. Aquí, hay dos tipos de problemas:

1. El Kernel, con la ayuda de la CPU, se

encarga de los detalles técnicos de cambio

de tarea.

Cada proceso individual se debe dar la

ilusión de que la CPU siempre está

disponible. Esta se logra salvando todos los

elementos dependientes del estado del

proceso antes de que los recursos de CPU

sean retirados y el proceso se coloca en un

estado de inactividad. Cuando el proceso se

reactiva, el estado exacto guardado o salvado es

restaurado. El cambio entre los procesos que se

conoce como cambio de tarea o cambio de

contexto.

2. El núcleo también debe decidir cómo el

tiempo de CPU se comparte entre los

procesos existentes. A los procesos

importantes se les da una mayor proporción

de tiempo de CPU, los procesos menos

importantes se les da una parte más

pequeña de tiempo. La decisión en cuanto a

qué proceso se ejecuta por cuánto tiempo se

conoce como scheduling.

5.2 PROCESOS DE UNIX

Linux utiliza un esquema jerárquico en el que cada

proceso depende de un proceso padre. El núcleo

inicia el programa init como el primer proceso que

es responsable de adoptar nuevas medidas de

inicialización del sistema y la visualización de la

pantalla de login o (en uso hoy en día más

extendida) de visualización de una interfaz gráfica

de acceso. init, es la raíz de donde se originan

todos los procesos, más o menos directamente,

como se muestra gráficamente.

Por el programa pstree. init es la parte superior de

una estructura de árbol cuyas ramas se

extienden más y más abajo.

Page 8: Arquitectura del Kernel Linux

wolfgang@meitner> pstree

init - + - acpid | - bonobo-activati | - cron | - cupsd | - 2 * [dbus-daemon] | - dbus-launch | - dcopserver | - dhcpcd | - esd | - eth1 | - events/0 | - gam_server | - gconfd-2 | - gdm - - - gdm - + - X | ‘ - startkde- + -kwrapper | ‘ -ssh-agent | - gnome – vfs – daemo | - gpg - agent | - hald – addon – acpi | - kaccess | - kded | - kdeinit - + - amarokapp---2*[amarokapp] | | - evolution-alarm | | - kinternet | | - kio_file | | - klauncher | | - konqueror | | - konsole---bash - + - pstree | | ‘ - xemacs | | - kwin | | - nautilus | ‘ - netapplet | - kdesktop | - kgpg | - khelper | - kicker | - klogd | - kmix | - knotify | - kpowersave | - kscd | - ksmserver | - ksoftirqd/0 | - kswapd0 | - kthread - + - aio/0 | | - ata/0 | | - kacpid | | - kblockd/0 | | - kgameportd | | - khubd

| | - kseriod | | - 2*[pdflush] | ‘ - reiserfs/0 ...

Cómo esta estructura de árbol se propaga está íntimamente relacionado con cómo los nuevos procesos se generan. Por este propósito, Unix utiliza dos mecanismos llamado fork y exec.

1. Fork: Genera una copia exacta del proceso

actual que difiere del proceso padre

sólo en su PID (identificación del proceso).

Después de que la llamada al sistema ha

sido ejecutada, hay dos procesos en el

sistema, tanto de realizar las mismas

acciones. El contenido de la memoria del

proceso inicial se duplica al menos en el

punto de vista del programa. Linux utiliza una

técnica conocida como copia en escritura,

que le permite hacer la operación mucho

más eficiente mediante el aplazamiento de

las operaciones de copia hasta que

cualquiera de los padres o el hijo escribe en

una página de sólo lectura, el acceso puede

ser satisfactorio desde la misma página para

ambos. Un escenario posible para el uso de

fork es, por ejemplo, cuando un usuario abre

una segunda ventana del navegador. Si la

opción correspondiente está seleccionada, el

navegador ejecuta un fork para duplicar su

código y luego empieza a las acciones

apropiadas para construir una nueva ventana

en el proceso hijo.

2. Exec: Carga un nuevo programa en un

contenido existente y luego se ejecuta. Las

páginas de memoria reservadas por el

antiguo programa se vacían, y sus

contenidos son reemplazados por nuevos de

datos. El nuevo programa se comienza a

ejecutar.

5.2.1 Hilos

Los procesos no son la única forma de ejecución

del programa apoyado por el núcleo. Además

heavy-weight process , otro nombre para los

procesos clásicos de Unix - también hay

discusiones, a veces se les denomina light-weight

processes. También han estado alrededor por

algún tiempo, y en esencia, un proceso puede

consistir en varios hilos que comparten los

mismos datos y recursos, sino tomar caminos

diferentes a través del código del programa. El

concepto de hilo está totalmente integrada en

muchas lenguas modernas - Java, por ejemplo. En

simples términos, un proceso puede ser visto

como un programa en ejecución, mientras que un

hilo es una función del programa o rutina

corriendo en paralelo al programa principal. Esto

es útil, por ejemplo, cuando los exploradores Web

que cargar varias imágenes en paralelo. Por lo

general, el navegador debería ejecutar varios

Page 9: Arquitectura del Kernel Linux

FORK y EXEC para generar instancias paralelas,

las cuales sería responsable de cargar las

imágenes y hacer que el programa recibida los

datos utilizando algún tipo de mecanismos de

comunicación. Temas que esta situación más fácil

de manejar. El navegador define una rutina para

cargar imágenes, y la rutina se inicia como un

tema con varios hilos (cada uno con diferentes

argumentos). Debido a que los hilos y los

principales compartir el espacio de direcciones

del programa mismo, los datos recibidos de forma

automática residir en el programa principal. Hay lo

que exime de cualquier esfuerzo de comunicación

alguna, para evitar que los hilos de refuerzo en

sus pies mutuamente mediante el acceso a

lugares de memoria idénticos, por ejemplo. Figura

2 ilustra la diferencia entre un programa con y sin

hilos.

Figura 2

Linux proporciona el método clone para generar

hilos. Esto funciona de manera similar a FORK,

pero permite una de verificación concreta que

deberá poner los recursos que son compartidos

con el proceso primario y que se generan

independientes para el hilo. Esta distribución de

grano fino de los recursos se extiende el concepto

hilo clásico y permite una transición más o menos

continua entre el hilo y procesos.

5.2.2 Espacios de nombres

(Namespaces)

Durante el desarrollo del kernel 2.6, el soporte

para espacios de nombres se integró en

numerosos subsistemas. Esto permite que los

diferentes procesos que tienen puntos de vista

diferentes del sistema. Tradicionalmente, Linux (y

Unix en general) utiliza numerosas cantidades

globales, por ejemplo, los identificadores de

proceso: Cada proceso en el sistema es equipado

con un identificador único (ID), y esta identificación

puede ser empleado por los usuarios (u otros

procesos) para referirse al proceso - mediante el

envío de una señal, por ejemplo. Con espacios de

nombres, anteriormente los recursos totales

agrupadas de manera diferente: Cada espacio de

nombres puede contener un conjunto específico

de las IDPs, donde se monta en un espacio de

nombres no se propagan en espacios de nombres

diferentes.

Los espacios de nombres son útiles, por ejemplo,

son beneficiosos para los proveedores de

alojamiento: En lugar de crear una máquina física

por cliente, en lugar pueden de utilizar

contenedores implementados con espacios de

nombres o namespaces a cabo de crear varias

vistas de la red en cada uno parece ser una

completa instalación de Linux desde dentro el

contenedor y no interactúa con otros

contenedores: Están separados y segregados

independiente de otros. Cada instancia se parece

a una sola máquina con Linux, pero de hecho,

muchos de estos casos pueden operar

simultáneamente en una máquina física. Esto

ayuda a usar los recursos de manera más eficaz.

En contraste con soluciones completas de

virtualización como KVM, sólo un núcleo único

debe ejecutar en el equipo y es responsable para

gestionar todos los contenedores.

No todas las partes del Kernel están plenamente

conscientes de espacios de nombres.

5.3 LOS ESPACIOS DE DIRECCIONES

Y NIVELES DE PRIVILEGIOS

Antes de empezar a discutir los espacios de direcciones virtuales, hay algunas convenciones de notación. Se utilizaran las abreviaturas KB, MB, GB y como unidades de tamaño. Las unidades convencionales KB, MB, y GB no son realmente adecuados en tecnología de la información, ya que representan los poderes decimal (10

2 ,10

6,

109) aunque el sistema binario es la base en la

computación. Debido a que las áreas de memoria se abordan a través de punteros, la longitud de la palabra de la CPU determina el tamaño máximo del espacio de direcciones que pueden ser manejados. En sistemas de 32 bits como IA-32, PPC, y m68k, se trata de 2

32 = 4 GB, mientras que en los

procesadores de 64-bit más modernos, como Alpha, Sparc64, IA-64, y AMD64, 2

64 bytes

pueden ser controlados.

Page 10: Arquitectura del Kernel Linux

El tamaño máximo del espacio de direcciones no está relacionado con la cantidad de RAM física que está realmente disponible, por lo que se conoce como el espacio de direcciones virtuales. Una razón más para esta terminología es que cada proceso en el sistema tiene la impresión de que sólo se viven en este espacio de direcciones, y otros procesos no están presentes desde su punto de vista. Las aplicaciones no necesitan preocuparse por otras aplicaciones y puede trabajar como si fueran a ejecutar como el único proceso en el equipo. Linux divide el espacio de direcciones virtuales en dos partes conocida como espacio de kernel y espacio de usuario como se ilustra en la Figura 3.

Figura 3.

Cada proceso de usuario en el sistema tiene su propio rango de direcciones virtuales que se extiende de 0 a TASK_SIZE. El área por encima (de TASK_SIZE a 2

32 o 2

64) está reservado

exclusivamente para el kernel y no puede ser accedido por los procesos de usuario. TASK_SIZE es una arquitectura específica constante que divide el espacio de direcciones en una razón dada - en los sistemas IA-32, por ejemplo, el espacio de direcciones se divide en 3 GB para que en el espacio virtual de direcciones cada proceso es de 3 GB, 1 GB está disponible para el kernel debido a que el tamaño total del espacio virtual de direcciones es de 4 GB. Aunque las cifras reales difieren de acuerdo a la arquitectura. Esta división no depende de la cantidad de RAM disponible. Como resultado de la virtualización del espacio de direcciones, cada proceso de usuario

cree que tiene 3 GB de memoria. El userspaces de los procesos del sistema están totalmente separados unos de otros. El espacio del Kernel en el extremo superior del espacio de direcciones virtuales es siempre el mismo, independientemente del proceso que se ejecuta actualmente.

5.4 5.3.1 Los niveles de privilegios

El núcleo se divide el espacio de direcciones virtuales en dos partes para que sea capaz de proteger los procesos del sistema uno del otro. Todas las CPU modernas ofrecen varios niveles de privilegio en el que los procesos pueden residen. Existen diversas prohibiciones en cada nivel, por ejemplo la ejecución de determinadas instrucciones o el acceso a determinadas partes del espacio de direcciones virtuales. La arquitectura IA-32 utiliza un sistema de cuatro niveles de privilegio que se puede visualizar en forma de anillos. Los anillos interiores son capaces de acceso a más funciones, como se muestra en la Figura 4.

Considerando que la variante Intel distingue cuatro niveles diferentes, Linux utiliza sólo dos modos diferentes en modo kernel y modo usuario. La diferencia clave entre los dos es que el acceso a la zona de memoria por encima de TASK_SIZE, es decir el espacio del núcleo está prohibido en modo de usuario. Los procesos de usuario no son capaces de manipular o leer los datos en el espacio del Kernel. Tampoco pueden ejecutar código almacenado allí. Este es el dominio exclusivo del Kernel. Este mecanismo evita que los procesos interfieran entre sí.

Page 11: Arquitectura del Kernel Linux

Figura 4 El cambio de usuario a modo de Kernel se realiza por medio de las transiciones especiales conocidas como llamadas al sistema (system calls), las cuales se ejecutan de manera diferente en función del sistema. Si un proceso normal quiere llevar a cabo cualquier tipo de acción que afecte a todo el sistema (por ejemplo, la manipulación de los dispositivos I / O), puede hacer esto sólo mediante la emisión de una solicitud al Kernel con la ayuda de una llamada al sistema. El Kernel comprueba primero si el proceso está permitido realizar la acción deseada y luego realiza la acción en su nombre. Además de la ejecución de código en nombre de un programa de usuario, el Kernel también puede ser activado por asincrónica interrupciones de hardware, y se dice entonces que se ejecutan en el contexto de interrupciones. La principal diferencia de ejecutar en el proceso contexto es que la porción del espacio de usuario del espacio de direcciones virtuales no se debe acceder. Debido a las interrupciones ocurren en momentos aleatorios, un proceso de espacio de usuario al azar se activa cuando se produce una interrupción, y puesto que la interrupción más probable es que no guarden relación con la causa de la interrupción, el Kernel no tiene que involucrarse con el contenido del espacio de usuario actual. Cuando se opera en el contexto de interrupciones, el Kernel debe ser más cauteloso de lo normal, por ejemplo, no debe ir a dormir. Una visión general de los diferentes contextos de ejecución se da en la Figura 5. Además de los procesos normales, también puede haber hilos en ejecución en el núcleo del sistema. Los hilos del Kernel son no está asociados a otro tipo de espacio de usuario particular, por lo que tampoco tienen relación con la porción del espacio de direcciones del usuario. En muchos otros aspectos, hilos del núcleo se comporta mucho más como aplicaciones regulares de entorno de

usuario, sin embargo: en contraste con un núcleo que operan en el contexto de interrupciones, que pueden ir a dormir, y también son rastreados por el scheduling como todo proceso ordinario en el sistema. El Kernel los utiliza para diversos fines que van desde la sincronización de datos de RAM y ayudar al scheduling a distribuir los procesos en

la CPU. Tenga en cuenta que los hilos del Kernel pueden ser fácilmente identificados en la salida del PS porque sus nombres se colocan entre paréntesis: wolfgang@meitner> ps fax

PID TTY STAT TIME COMMAND

2 ? S< 0:00 [kthreadd] 3 ? S< 0:00 _ [migration/0] 4 ? S< 0:00 _ [ksoftirqd/0] 5 ? S< 0:00 _ [migration/1] 6 ? S< 0:00 _ [ksoftirqd/1] 7 ? S< 0:00 _ [migration/2] 8 ? S< 0:00 _ [ksoftirqd/2] 9 ? S< 0:00 _ [migration/3] 10 ? S< 0:00 _ [ksoftirqd/3] 11 ? S< 0:00 _ [events/0] 12 ? S< 0:00 _ [events/1] 13 ? S< 0:00 _ [events/2] 14 ? S< 0:00 _ [events/3] 15 ? S< 0:00 _ [khelper] 16 ? S< 0:00 …

15162 ? S< 0:00 _ [jfsCommit] 15163 ? S< 0:00 _ [jfsSync]

Page 12: Arquitectura del Kernel Linux

Figura 5.

Figura 5: Ejecución en el modo Kernel y usuario. La mayoría de las veces, la CPU ejecuta código en espacio de usuario. Cuando la aplicación realiza una llamada al sistema, el paso a modo Kernel se emplea, y el Kernel cumple la solicitud. Durante este periodo, se puede acceder a la parte del espacio de direcciones virtuales del usuario. Después de la llamada del sistema se completa, la CPU cambia de nuevo al modo de usuario. Una interrupción de hardware activa un interruptor que pasa de nuevo a modo Kernel, pero esta vez, la porción del espacio de usuario no debe tener acceso al Kernel.

En los sistemas multiprocesador, muchos hilos se les pone en una base por la CPU y se limitan a contar a partir sólo un procesador específico. Esto está representado por una barra y el número de la CPU que se anexan al nombre del hilo del núcleo.

5.3.2 Espacios virtuales y físicos

En la mayoría de los casos, un único espacio de direcciones virtuales es más grande que la memoria RAM física disponible para el sistema. Y la situación no mejora cuando cada proceso tiene su propio espacio de direcciones virtuales. El Kernel y la CPU, deben considerar cómo la memoria física realmente esta disponible para que pueda incorporar a las áreas de dirección virtual.

El método preferido es usar las tablas de páginas para asignar direcciones virtuales a direcciones físicas. Mientras direcciones virtuales se relacionan con el usuario combinado, así como el espacio del Kernel de un proceso, se utilizan las direcciones físicas para hacer frente a la RAM disponible. Este principio se ilustra en la Figura 6. Los espacios de direcciones virtuales de ambos procesos se muestra en la figura se dividen en porciones de igual tamaño por el Kernel. Estas porciones son conocidas como páginas. La memoria física se divide también en las páginas del mismo tamaño.

Figura 6.

Las flechas en la figura 6 indican cómo las páginas de los espacios de direcciones virtuales se distribuyen a través de las páginas físicas. Por ejemplo, una página virtual del proceso se asigna a una página física 4, mientras virtual la página 1 del proceso B se asigna a la página física quinto. Esto muestra que las direcciones virtuales cambian el significado de un proceso a otro. Páginas físicas a menudo son llamados marcos de página. En contraste, la término página se reserva para las páginas virtuales en espacio de direcciones. El mapeo entre los espacios de direcciones virtuales y la memoria física también permite la separación estricta entre los procesos. Nuestro ejemplo incluye un marco de página de forma explícita compartida por ambos procesos. Página 5 de A y B de la página 1 punto tanto para el marco de página física 5. Esto es posible porque entradas en ambos espacios de direcciones virtuales (aunque en diferentes posiciones) apuntan a la misma página. El Kernel es responsable de asignar espacio de direcciones virtuales al espacio de direcciones físico, es capaz de decidir qué áreas de memoria han de ser compartidos entre los procesos y cuáles no. La figura también muestra que no todas las páginas de los espacios de direcciones virtuales están vinculadas con un marco de página. Esta puede ser, ya sea porque las páginas no se utilizan o porque los datos no han sido cargados en la memoria porque todavía no son necesarios.

Page 13: Arquitectura del Kernel Linux

También puede ser que la página ha sido cambiada en el disco duro y serán intercambiados en cuando es necesario. Por último, observe que hay dos términos equivalentes para hacer frente a las aplicaciones que se ejecutan en nombre del usuario. Uno de ellos es espacio de usuario, y esta es la nomenclatura generalmente preferido por la comunidad BSD para todas las cosas que no pertenecen al núcleo. La alternativa es decir que una aplicación se ejecuta en espacio de usuario. Lo Cabe señalar que la zona de usuario siempre significará aplicaciones como tal, mientras que el espacio de usuario puede además no sólo las aplicaciones denotan, sino también la porción del espacio de direcciones virtuales en las que se ejecutan, en contraste con el espacio del Kernel.

5.4 TABLAS DE PAGINAS

Las estructuras de datos conocidas como tablas de páginas se utilizan para asignar espacio de direcciones virtuales al espacio de direcciones físicas. La forma más sencilla de aplicar la asociación entre ambos sería utilizar una matriz que contiene una entrada para cada página en el espacio de direcciones virtuales. Esta entrada se elije el marco de página asociado. Pero hay un problema. La arquitectura IA-32 utiliza por ejemplo, páginas 4 KB, cuenta con un espacio de direcciones virtual de 4 GB, esto produciría una matriz con un millón de entradas. En arquitecturas de 64-bit, la situación es mucho peor. Debido a que cada proceso tiene su propia página tablas, este enfoque es práctico, porque la memoria RAM total del sistema sería necesaria para mantener las tablas de páginas. Como la mayoría de las zonas de los espacios de direcciones virtuales no se utilizan, por lo que no está asociada con marcos de página, un modelo de memoria mucho menos intensivo que cumpla con la misma finalidad: se puede utilizar paginación multinivel. Para reducir el tamaño de las tablas de la página y permitir que algunas zonas que no sean ignoradas, se divide cada una de las direcciones virtuales en varias partes, como se muestra en la Figura 7 (las posiciones de bit en la que la dirección se divide difieren de acuerdo a la arquitectura, pero esto es irrelevante aquí). En el ejemplo se usa una fracción virtual de la dirección en cuatro componentes, y esto conduce a una tabla de páginas de tres niveles. Esto es lo que la mayoría de arquitecturas ofrecer. Sin embargo, algunos emplean cuatro niveles tablas de páginas, y Linux también adopta cuatro niveles de direccionamiento indirecto.

Figura 7.

La primera parte de la dirección virtual se conoce como un directorio de páginas global o PGD. Se utiliza como un índice en una matriz que existe exactamente una vez para cada proceso. Sus entradas son punteros del inicio de las matrices más llamada de directorios de páginas medio o PMD. Una vez que la matriz correspondiente se ha constatado que la DGP y su contenido, el PMD se utiliza como un índice para la matriz. El directorio de media página también consta de punteros a las matrices más conocidos como las tablas de páginas o directorios de páginas. El PTE (o entrada de la tabla de página) parte de la dirección virtual se utiliza como un índice para la tabla de páginas. Cartografía entre las páginas virtuales y marcos de página se logra porque las entradas de la tabla de páginas apuntan a marcos de página. La última parte de la dirección virtual que se conoce como un desplazamiento. Se utiliza para especificar una posición de byte en la página, después de todo, cada uno de los puntos de dirección a un byte único definido en el espacio de direcciones. Una característica particular de las tablas de páginas es que no hay tablas de páginas medio o tablas de páginas necesitan ser creadas para las áreas de espacio de direcciones virtuales que no son necesarios. Esto ahorra una gran cantidad de memoria RAM en comparación con el de una sola matriz. Por supuesto, este método también tiene su lado negativo. Cada vez que se accede de memoria, es necesario ejecutar a través de toda la cadena para obtener la dirección física de la dirección virtual. La CPU trata de acelerar este proceso de dos maneras:

1. Una parte especial de la CPU se conoce como una unidad de gestión de memoria (MMU) está optimizado para llevar a cabo las operaciones de referencia.

Page 14: Arquitectura del Kernel Linux

2. Las direcciones que aparecen con más frecuencia en la dirección de traducción se llevan a cabo de una forma rápida caché de CPU llamando Traducción Lookaside Buffer (TLB). La traducción es acelerada porque la dirección de los datos en la memoria caché están disponibles de inmediato sin necesidad de acceder a las tablas de páginas y por lo tanto la memoria RAM. Mientras cachés son operados de forma transparente en muchas arquitecturas, algunos requieren especial la atención del Kernel, que sobre todo implica que su contenido debe ser invalidada siempre que el contenido de las tablas de páginas han sido cambiados. Correspondiente las llamadas tienen que presente en todas las partes del Kernel que manipula las tablas de páginas. Si el kernel está compilado para una arquitectura que no requiere este tipo de operaciones, automáticamente se asegura de que las llamadas están representados por las operaciones que no hacen nada.

5.4.1 Interacción con la CPU La arquitectura IA-32 utiliza un método de dos niveles. Sólo asignar direcciones virtuales a direcciones físicas. El tamaño del espacio de direcciones en las arquitecturas de 64-bit (Alfa, Sparc64, IA-64, etc.) los mandatos de una de tres niveles o método de cuatro niveles, y la parte de la arquitectura independiente del Kernel siempre supone un nivel de cuatro tabla de páginas. El código dependiente de la arquitectura del núcleo de dos y tres CPUs niveles tanto, debe emular el faltan los niveles de tablas de páginas ficticias. En consecuencia, el código de administración de memoria restante puede ser aplicarse con independencia de la CPU utilizada.

5.4.2 Asignaciones de memoria Las asignaciones de memoria son un medio importante de la abstracción. Se utilizan en muchos puntos en el Kernel y también están disponibles para aplicaciones de usuario. El mapeo es el método por el cual los datos de una fuente arbitraria se transfieren en el espacio de direcciones virtuales de un proceso. Las áreas de espacio de direcciones en las que la cartografía se lleva a cabo pueden ser procesados mediante los métodos habituales de la misma manera como memoria normal. Sin embargo, cualquier cambio realizado es transferido automáticamente a la fuente de datos original. Esto hace posible el uso de funciones idénticas a procesar las cosas totalmente diferentes. Por ejemplo, el contenido de un archivo se puede asignar en la memoria. A

continuación, el proceso sólo necesita leer el contenido de la memoria para acceder al contenido del archivo, o cambios escritos en la memoria con el fin de modificar el contenido del archivo. El Kernel asegura automáticamente que cualquier cambio hecho se implemente en el archivo. Las asignaciones también se utilizan directamente en el Kernel en la aplicación de controladores de dispositivos. La entrada y salida de los dispositivos periféricos se pueden asignar áreas en el espacio de direcciones virtuales, lee y escribe en estas áreas luego se redirige a los dispositivos del sistema, lo que simplifica enormemente la implementación del controlador.

5.5 ASIGNACIÓN DE MEMORIA FÍSICA Cuando se asigna memoria RAM el núcleo debe llevar un registro de las páginas que ya han sido asignados y que sigue siendo libre con el fin de evitar el uso de dos procesos de las mismas áreas en la memoria RAM. Porque la asignación de memoria y liberación son tareas muy frecuentes, el Kernel también deben asegurarse de que se desarrollen lo más rápidamente posible. El Kernel puede asignar sólo marcos de página entera. La división más pequeña de memoria en porciones se delega en la biblioteca estándar de espacio de usuario. Esta biblioteca se divide la página de marcos recibido desde el Kernel en áreas más pequeñas y la memoria asigna a los procesos.

5.5.1 El sistema de apadrinamiento (buddy system)

Gran número de solicitudes de asignación en el Kernel deben ser cumplidas por una serie continua de páginas. Para rápidamente detectar en qué rangos de memoria aun están disponibles, el Kernel emplea una vieja, pero la técnica probada: El sistema de apadrinamiento. Bloques de memoria libre en el sistema siempre se agruparán en como dos amigos. Los amigos pueden ser asignados independientemente unos de otros, y sin embargo, ambos no siguen siendo utilizados al mismo tiempo, el Kernel los confunde en un par más grande que sirve como un compañero en el siguiente nivel. Figura 8 muestra este ejemplo, utilizando una de un par de amigos constituido inicialmente por dos bloques de 8 páginas.

Page 15: Arquitectura del Kernel Linux

Figura 8.

Cuando la memoria es devuelta por la solicitud, el Kernel puede ver fácilmente en función de las direcciones si un par de amigos se reúne y después pueden fundirse en una unidad más grande que se pone de nuevo en el compañero lista, exactamente lo contrario del proceso de fraccionamiento. Esto aumenta la probabilidad de que grandes bloques de memoria están disponibles. Cuando los sistemas funcionan durante más tiempo no es raro que los servidores para una duración de varias semanas o incluso meses, y muchos sistemas de escritorio también tender a alcanzar largo tiempo de actividad, un problema de gestión de memoria conocida como la fragmentación se produce. La asignación de frecuencia y la liberación de marcos de página puede llevar a una situación en el que varios fotogramas página son libres en el sistema, pero se encuentran dispersas en la dirección física espacio - en otras palabras, no hay grandes bloques contiguos de marcos de página, como sería deseable para motivos de rendimiento. Este efecto se reduce en

cierta medida por el sistema de amigos pero no del todo eliminados. Individual páginas reservadas que se sientan en medio de una gran variedad de otro modo libre contiguo puede eliminar la coalescencia de este rango de manera muy eficaz. Durante el desarrollo del Kernel 2.6.24, algunos efectivas medidas se han añadido para evitar la fragmentación de memoria.

5.5.2 El bloque de Chache

A menudo el propio Kernel necesita bloques de memoria mucho más pequeño que un marco de página entera. Debido a que no se puede utilizar las funciones de la biblioteca estándar, que debe definir su propia capa adicional de gestión de memoria que se basa en el sistema de amigos y divide las páginas proporcionadas por el sistema de compañeros en porciones más pequeñas. El método utilizado no sólo realiza la asignación, sino también implementa un caché genéricos utilizados frecuentemente objetos pequeños, lo que se conoce como caché de un caché de la losa. Se puede utilizar para asignar memoria de dos maneras:

Page 16: Arquitectura del Kernel Linux

1. Para los objetos de uso frecuente, el Kernel define su propia caché que contiene únicos casos de el tipo deseado. Cada vez que uno de los objetos se requiere, puede ser eliminado rápidamente de la caché (y regresó allí después de su uso), el caché de la losa se encarga automáticamente de interacción con el sistema de amigos y nuevas peticiones de marcos de página cuando el cachés existentes están llenos.

2. Para el reparto general de los bloques de

memoria más pequeñas, el Kernel define un conjunto de cachés losa para los tamaños de objetos diversos que se accede con las mismas funciones con las que estamos familiarizados de la programación del espacio de usuario; un prefijo k indica que estas funciones están asociadas con el Kernel: kmalloc y kfree.

Mientras que el asignador slab proporciona un buen rendimiento en una amplia gama de cargas de trabajo, algunos problemas de escalabilidad con él han surgido en los superordenadores de gran tamaño. Por otro lado de la escala, la sobrecarga del asignador slab puede ser demasiado para sistemas embebidos muy pequeños. El Kernel viene con dos DROPIN reemplazos para el asignador slab que proporcionan un mejor rendimiento en estos casos de uso, pero ofrecen la misma interfaz para el resto del núcleo de tal manera que no necesita preocuparse con la que baja el nivel de imputación es en realidad compilado pulg Desde la asignación de losa sigue los métodos estándar del kernel, lo haré, sin embargo, no discutir estas alternativas en detalle. Figura 9 se resumen las conexiones entre el sistema de amigos, asignador slab, y el resto del núcleo.

5.5.3 Swapping and page Reclaim

Swapping habilita la RAM disponible para ser ampliada mediante el uso de prácticamente espacio en disco como memoria extendida. Con poca frecuencia las páginas más utilizadas se pueden escribir en el disco duro cuando el Kernel necesita más memoria RAM. Una vez que los datos son realmente necesarios, el kernel regresa a memoria. El concepto de fallos de página se utiliza para hacer esta operación transparente para las aplicaciones. Intercambiaando páginas de salida se identifican por una entrada especial en la tabla de páginas. Cuando un proceso intenta acceder a una página de este tipo, la CPU inicia un error de página que se interceptada por el Kernel. El Kernel tiene entonces la oportunidad de intercambiar los datos del disco a la RAM. El proceso de usuario a continuación, vuelve a sonar.

Debido a que no se da cuenta del error de página, cambiando dentro y fuera de la página es totalmente invisible para el proceso.

Figura 9.

Page Reclaim se utiliza para sincronizar modificaciones con asignaciones de dispositivos de bloque subyacentes por esta razón, a veces es referido simplemente como escribir de nuevo los datos. Una vez que los datos se han volcado, el marco de página puede ser utilizada por el kernel para otros fines (como intercambio). Después de todo, los datos del Kernel son estructuras que contienen toda la información necesaria para encontrar los datos correspondientes en el disco duro cuando están de nuevo requeridos.

5.6 EL TIEMPO

El Kernel debe ser capaz de medir las diferencias de tiempo en varios puntos al programar procesos, por ejemplo Jiffies son una base de tiempo posible. Una variable global llamada jiffies_64 y sus 32-bit jiffies contrapartida se

incrementan periódicamente a intervalos de tiempo constante. El temporizador de varios mecanismos de las arquitecturas subyacentes se utilizan para realizar estas actualizaciones - cada arquitectura de computadores proporciona un medio de ejecución de las acciones periódicas, generalmente en forma de interrupciones del temporizador. Dependiendo de la arquitectura, jiffies se incrementa con una frecuencia determinada por el centro de constante HZ del Kernel. Esto es por lo general en el rango entre 1.000 y 100, es decir, el valor de unidades de tiempo se incrementa entre los 1.000 y 100 veces por segundo. La sincronización basada en unidades de tiempo es relativamente de grano grueso, ya 1.000 Hz no es una frecuencia excesivamente grande hoy en día. Con los cronómetros de alta resolución, el Kernel proporciona medios adicionales que

Page 17: Arquitectura del Kernel Linux

permite de mantenimiento de hoy en el gobierno de la precisión y la resolución de nanosegundos, dependiendo de las capacidades del hardware subyacente. Es posible hacer el tick dynamic. Cuando periódicamente hay poco que hacer y no hay necesidad de frecuentes acciones, no tiene sentido para generar interrupciones periódicas del temporizador que impiden que el procesador de se apague en los estados de sueño profundo. Esto es útil en sistemas donde el poder es escaso, por ejemplo, computadoras portátiles y sistemas incorporados.

5.7 LLAMADAS AL SISTEMA (SYSTEM

CALLS)

Las llamadas al sistema son el método clásico de los procesos de usuario que permite interactuar con el Kernel. La POSIX norma define una serie de llamadas al sistema y sus efectos en la práctica en todos los sistemas compatibles con POSIX

incluyendo Linux. Las llamadas de sistema se agrupan en varias categorías: Procesos Management: Creación de nuevas

tareas, consultar información, depuración. Señales: El envío de señales, contadores de

tiempo, los mecanismos de control. Archivos: Crear, abrir y cerrar archivos, leer y

escribir a los archivos, consultar información y el estado. Directorios y archivos del sistema: Creación

del sistema de archivos y directorios, borrar, y renombrar directorios, consultar información, enlaces, cambiar directorios. Mecanismos de protección: Lectura y cambiar

UID GID / y el manejo de espacio de nombres. Funciones del temporizador: Funciones de

temporizador y de información estadística. Todas estas funciones son colocadas en el Kernel. No se puede implementar en un usuario normal bibliotecas porque los mecanismos especiales de protección son necesarias para garantizar que la estabilidad del sistema y / o de seguridad no están en peligro de extinción. Además, muchas llamadas dependen de las estructuras internas del núcleo o funciones para dar datos deseados o los resultados - esto también dicta contra la aplicación en espacio de usuario. Cuando una llamada al sistema es emitidos, el procesador debe cambiar el nivel de privilegios y cambiar de modo de usuario a modo de sistema. Hay una forma

normalizada de hacer esto en Linux, ya que cada plataforma de hardware ofrece mecanismos específicos. En algunos casos, los diferentes enfoques se aplican en la misma arquitectura, pero dependen de procesadores tipo. Considerando que Linux utiliza una interrupción de software especiales para ejecutar las llamadas al sistema de procesadores IA-32, el emulación por software (GRG emulador) de otros sistemas Unix en IA-32 utiliza un método diferente para ejecutar programas binarios (para los aficionados al lenguaje ensamblador: el lcall7 lcall27 o puerta). Moderno variantes de IA-32 también tienen su propia declaración en lenguaje ensamblador para la ejecución de las llamadas al sistema, lo que fue no está disponible en el sistema antiguo y no puede por tanto ser utilizado en todas las máquinas. Qué tienen en todas las variantes común es que las llamadas al sistema son la única manera de permitir que los procesos de usuario para cambiar en sus propios incentivos desde el modo usuario a modo de Kernel con el fin de delegar funciones críticas del sistema.

5.8 CONTROLADORES DE DISPOSITIVOS, DISPOSITIVOS DE BLOQUE Y DE CARACTERES

El papel de los controladores de dispositivo es para comunicarse con dispositivos I / O conectados al sistema, por ejemplo, discos duros, disquetes, interfaces, tarjetas de sonido, y así sucesivamente. De acuerdo con la filosofía de Unix ''Todo es un archivo'', el acceso se realiza mediante los ficheros de dispositivos que normalmente residen en el directorio / dev / y pueden ser procesados por programas de la misma manera como archivos normales. La tarea de un controlador de dispositivo es apoyar comunicación con aplicaciones a través de ficheros de dispositivo, es decir, para permitir que los datos que se deben leer y escribir en un dispositivo de forma adecuada. Los dispositivos periféricos pertenecen a uno de los dos grupos siguientes:

1. Dispositivos de caracteres: Entregar un flujo continuo de datos que las aplicaciones de lectura secuencial; en general, de acceso aleatorio no es posible. En su lugar, estos dispositivos permiten que los datos que se deben leer y escrita byte a byte o un carácter por carácter. Los módems son ejemplos clásicos de dispositivos carácter.

2. Dispositivos de bloque: Permitir que las aplicaciones para hacer frente a sus datos al azar y seleccionar libremente la posición en

Page 18: Arquitectura del Kernel Linux

la que quieren leer los datos. Los accesorios típicos bloque son los discos duros ya que las aplicaciones puede abordar cualquier posición en el disco desde la que leer los datos. Además, los datos se pueden leer o por escrito sólo en múltiplos de las unidades de bloque (bytes por lo general 512); abordar basada en caracteres, como en dispositivos de caracteres, no es posible.

Programación de controladores para dispositivos de bloque es mucho más complicada que la de los dispositivos de carácter debido a complejos mecanismos de almacenamiento en caché se utilizan para aumentar el rendimiento del sistema.

5.9 NETWORKS Las tarjetas de red también son controladas por los controladores de dispositivos, pero asume una condición especial en el Kernel, porque que no se pueden abordar con los ficheros de dispositivos. Esto es porque los datos se empaquetan en capas de protocolo diferentes durante la comunicación de red. Cuando se reciban los datos, las capas deben ser desmontados y analizados por el Kernel antes de la carga útil de datos se pasan a la solicitud. Cuando los datos son enviados, el Kernel debe primero verificar si los paquetes de los datos en las capas posen un protocolo diferentes antes de su expedición. Sin embargo, para apoyar el trabajo con conexiones de red a través de la interfaz de archivo (en la vista de las solicitudes), Linux utiliza sockets BSD, los cuales actúan como agentes entre las aplicaciones, interfaces de archivos y la implementación de red del Kernel.

5.10 FILESYSTEMS Los Sistemas Linux se componen de muchos miles o incluso millones de archivos cuyos datos se almacenan en duro discos u otros dispositivos de bloque (por ejemplo, unidades ZIP, disquetes, CD-ROM, etc.) sistemas de archivos jerárquica se utilizan; éstos permiten almacenar datos que se organizan en una estructura de directorios y también tienen la tarea de vincular otros meta-datos (propietarios, los derechos de acceso, etc) con los datos reales. Muchos enfoques diferentes sistemas de archivos son compatibles con Linux los sistemas de ficheros estándar de Ext2 y Ext3, ReiserFS, XFS, VFAT (por razones de compatibilidad con DOS) y muchos más. Los conceptos sobre los que construir difieren drásticamente en parte. Ext2 es sobre la base de inode, es decir, tiene una estructura de gestión independientes conocidos como un inode disponibles en disco para cada archivo. El inode

contiene no sólo todos los meta-datos, sino también punteros a los asociados bloques de datos. Las estructuras jerárquicas son creados por los directorios que representan como archivos normales cuyos datos sección incluye enlaces a los inodos de todos los archivos contenidos en el directorio. Por el contrario, ReiserFS hace un amplio uso de estructuras de árbol para ofrecer la misma funcionalidad. El Kernel debe proporcionar una capa de software adicional para abstraer las características especiales de los distintos bajo nivel del tipo sistemas de ficheros de la capa de aplicación (y también desde el propio núcleo). Esta capa se conoce como el VFS (sistema de archivos virtual o cambiar sistema de archivos virtual). Actúa como interfaz hacia abajo (esta interfaz deben ser aplicadas por todos los sistemas de ficheros) y hacia arriba (para las llamadas de sistema a través de procesos de usuario que son en última instancia para poder acceder a las funciones de sistema de archivos). Esto se ilustra en la Figura 10.

Figura 10.

5.11 MÓDULOS Y HOTPLUGGING

Los módulos se usan para añadir dinámicamente funcionalidad al Kernel en tiempo de ejecución, controladores de dispositivos, sistemas de ficheros, protocolos de red, prácticamente en cualquier subsystem3 del núcleo se pueden modular. Esto quita una de las desventajas significativas de los núcleos monolíticos, en comparación con las variantes microkernel. Los módulos también pueden ser descargados desde el Kernel en tiempo de ejecución, un aspecto útil en el desarrollo de nuevos componentes en el Kernel. Básicamente, los módulos son simplemente programas normales que se ejecutan en espacio de Kernel y no en espacio de usuario. Asimismo, deberá ofrecer ciertas secciones que se ejecutan

Page 19: Arquitectura del Kernel Linux

cuando el módulo se inicializa (y terminado) con el fin de registrar y de registro, las funciones del módulo con el Kernel. De lo contrario, el código de módulo los mismos derechos (y obligaciones) como código de Kernel normal y se puede acceder a todas las mismas funciones y datos código que está permanentemente compilado en el núcleo.

Un problema de larga trayectoria en la comunidad del núcleo gira en torno al apoyo de módulos binarios-solamente, es decir, módulos cuyo código fuente no está disponible. Mientras que los módulos binarios sólo son omnipresentes en la mayoría de sistemas operativos propietarios, muchos desarrolladores del núcleo permiten verlos como una encarnación actualmente es posible cargar módulos binarios en el núcleo, a pesar de numerosas restricciones se aplican para ellos. Lo más importante es que no pueden acceder a las funciones que son explícitamente sólo a disposición de código con licencia GPL. Si el Kernel se está contaminado, será marcado en accidentes vertederos culpando al modulo implantado en el Kernel, ya que el módulo binario podría haber dado todas las partes del Kernel de buen funcionamiento, no se puede suponer que el núcleo sigue funcionando según lo previsto, es mejor dejar al fabricante culpe al módulo. Cargando los módulos binarios sólo no es la única posibilidad de contaminar un núcleo. Esto sucede también cuando, por ejemplo, la máquina ha experimentado ciertas excepciones, cuando un sistema SMP se construye con las CPUs que no soporta oficialmente multiprocesamiento por sus especificaciones, y otras razones similares.

5.12 EL ALMACENAMIENTO EN CACHÉ (CACHING)

El Kernel utiliza cachés para mejorar el rendimiento del sistema. Los datos leídos de dispositivos de bloque lento se llevan a cabo en la memoria RAM por un tiempo, aunque ya no son necesarios en el momento. Cuando una aplicación accede a los próximos los datos, se puede leer desde la memoria RAM rápida, evitando así el dispositivo de bloque lento. Dado que el núcleo implementa el acceso a los dispositivos de bloque a través de la página de mapas de memoria, cachés también están organizados en páginas, es decir, páginas enteras se almacenan en caché, lo que daría lugar a la caché de nombre de la página. El buffer cache mucho menos importante se utiliza para caché de datos que no están organizadas en páginas. Tradicionalmente en sistemas Unix, la caché del búfer sirve como el caché del sistema principal, y el mismo enfoque fue utilizado por Linux desde hace mucho tiempo, hace mucho tiempo. Por ahora, la caché del búfer en su

mayoría ha sido sustituida por la caché de la página.

5.13 LISTA DE MANEJO

Una tarea recurrente en los programas en C es el manejo de listas doblemente enlazadas. El Kernel también se requiere para manejar dichas listas. En este punto se nombra una breve introducción a la lista de manipulación de la API. Las listas habituales de lo dispuesto por el Kernel pueden ser utilizadas para conectar las estructuras de datos de cualquier tipo entre sí. Queda expresamente no con seguridad de tipos. Las estructuras de datos para ser enumeradas deben contener un elemento de tipo list_head, lo que se adapta a los punteros hacia adelante y hacia atrás. Si una estructura de datos es que se organizará en varias listas - y esto no es inusual - varios elementos list_head son necesarios.

<list.h>

struct list_head {

struct list_head *next, *prev;

};

This element could be placed in a

data structure as follows:

struct task_struct {

...

struct list_head run_list;

...

};

El punto de partida de las listas enlazadas es de nuevo una instancia de list_head que normalmente se declara y se inicializa por el LIST_HEAD (list_name) macro. De esta manera,

el Kernel genera una lista cíclica, como se muestra en Figura 11. Permite el acceso al primer elemento y el último de una lista es decir, siempre la misma constante de tiempo, independientemente del tamaño de la lista.

Figura 11.

La estructura list_head se llama un elemento de la lista cuando se sostiene en una estructura de datos. Un elemento que sirve de punto de partida de una lista se denomina lista de la cabeza.

Page 20: Arquitectura del Kernel Linux

Punteros que conectan la cabeza y los elementos de la cola de una lista tienden a estorbar encima de las imágenes y menudo obstruyen el propósito principal de una figura, es decir, para resumir brevemente las conexiones de las diversas estructuras de datos del Kernel. Por lo general omiten la conexión entre la cabeza y la cola lista de la lista en cifras. La lista anterior es en lo que resta de este libro, por tanto representados como se muestra en la Figura 12. Esto permite concentrar sobre los detalles esenciales, sin tener que perder el espacio para punteros lista irrelevante.

Figura 12: ilustración simplificada de una doble lista enlazada. Observe que la conexión entre cabeza de lista y la cola lista no aparece, aunque está presente en memoria del núcleo. Hay varias funciones para la manipulación y procesamiento de listas:

list_add (new, head): se inserta el

nuevo derecho después de que el elemento head existentes.

list_add_tail (new, head): se

inserta el nuevo derecho antes de que el elemento especificado por la cabeza. Si la lista de la cabeza se especifica para la cabeza, esto hace que el nuevo elemento que se inserta al final de la lista a causa de la naturaleza cíclica de la lista (así le da la función de su nombre).

list_del (entry): se elimina una

entrada de una lista.

list_empty (head): comprueba si una

lista está vacía, es decir, si no contiene ningún elemento.

list_splice (list, head): combina

dos listas mediante la inserción de la lista de la lista después de que el elemento head de una lista existente.

list_entry: debe ser utilizado para

encontrar un elemento de la lista; a primera vista, su sintaxis de llamada parece ser bastante complicado: list_entry (ptr,

type, member). ptr es un puntero a la

instancia list_head de la estructura de

datos, el tipo es su tipo, y miembro es el nombre del elemento utilizado para el elemento de la lista. Tras el llamamiento de la muestra que se necesitaría para encontrar una task_struct instancia de una lista:

struct task_struct = list_entry(ptr,

struct task_struct, run_list)

Especificación explícita, es necesario utilizar porque la aplicación en la lista no es de tipo seguro. La lista de elementos Se debe especificar para encontrar el elemento correcto si hay estructuras de datos que se incluyen en varias listas.

list_for_each (pos, head): debe ser

utilizado para recorrer todos los elementos de una lista. pos indica la posición actual de la lista, mientras que la cabeza se especifica la lista de la cabeza.

struct list_head *p;

list_for_each(p, &list)

if (condition)

return list_entry(p, struct

task_struct, run_list);

return NULL;

5.14 GESTIÓN DE OBJETOS Y RECUENTO DE REFERENCIAS

En todo el Kernel, la necesidad de realizar un seguimiento de los casos de las estructuras de C se presenta. A pesar del hecho de que estos objetos se utilizan en las más diversas formas, algunas operaciones son muy similares entre los subsistemas sólo considerar recuento de referencias. Esto conduce a la duplicación del código. Dado que esta es una cosa mala, el Kernel tiene adoptó métodos genéricos para administrar los objetos del núcleo durante el desarrollo de 2,5. El marco es, Sin embargo, no sólo para evitar la duplicación de código. También permite ofrecer una visión coherente sobre la objetos gestionados por diferentes partes del Kernel, y esta información puede ser llevada a buen uso en muchas partes del Kernel, por ejemplo, para la administración de energía. El mecanismo de objetos genéricos del núcleo se puede utilizar para realizar las siguientes operaciones sobre los objetos:

Conteo de referencias

gestión de las listas (conjuntos) de objetos

bloqueo de los conjuntos

Exportadores de propiedades de objetos en espacio de usuario (a través del sistema de ficheros sysfs).

Page 21: Arquitectura del Kernel Linux

5.14.1 Objetos genéricos Kernel La siguiente estructura de datos que se incrusta en otras estructuras de datos se utiliza como base. <kobject.h>

struct kobject {

const char * k_name;

struct kref kref;

struct list_head entry;

struct kobject * parent;

struct kset * kset;

struct kobj_type * ktype;

struct sysfs_dirent * sd;

};

Es esencial los kobjects no están vinculados

con otras estructuras de datos por medio de punteros, pero se incrustan directamente. El administrar el kernel objeto mismo asciende a la gestión de todo el objeto que contiene esta manera. Desde struct kobject se incrusta en muchas estructuras de datos del núcleo, los desarrolladores tener cuidado de mantenerla pequeña. Añadiendo un nuevo elemento a esta única estructura de datos de resultados en un aumento de tamaño de muchos otras estructuras de datos. Objetos incrustados en el Kernel. El significado de los distintos elementos de estructura kobject son los siguientes:

k_name es un nombre de texto exportado al

espacio de usuario usando sysfs. Sysfs es

un sistema de ficheros virtual que permite la exportación de varias propiedades del sistema en espacio de usuario.

KREF mantiene la estructura general del tipo

KREF para simplificar la gestión de

referencia.

Entry es un elemento de la lista estándar

que se utiliza para agrupar varios kobjects

en una lista (conocida como un conjunto en este caso).

kset es necesario cuando un objeto se

agrupa con otros objetos en un conjunto.

parent es un puntero al elemento padre y

permite una estructura jerárquica que se establecerá entre kobjects.

type proporciona información más

detallada sobre la estructura de datos en la que una es kobject incrustado. De mayor

importancia es la función que devuelve el destructor de los recursos de la incrustación de estructura de datos.

La similitud entre el nombre y kobject , el concepto de objeto además, los lenguajes orientados a

objetos como C + + o Java no es en absoluto casual: La abstracción kobject hecho permite utilizar orientado a objetos técnicas en el Kernel, pero sin exigir todos los mecánicos adicionales (y la hinchazón, y los gastos generales) de C + +. Tabla 1 enumera las operaciones estándar que ofrece el núcleo para manipular kobject casos, y por lo tanto efectivamente actuar sobre la estructura de inserción. El diseño de la estructura VREF se utiliza para gestionar las referencias, es el siguiente: <kref.h>

struct kref {

atomic_t refcount;

};

refcount es un tipo de datos atómicos para

especificar el número de posiciones en el Kernel en el que un objeto es actualmente se está utilizando. Cuando el contador llegue a 0, el objeto ya no es necesario y puede ser borrado de la memoria. Tabla 1 metodos de norma para procesamiento de Kobjects

Función Significado kobject_get,

kobject_put

Los incrementos o decrementos del contador de referencias de un kobject

kobject_(un)register Registros o eliminacion obj de una jerarquía (el objeto se añade a la existentes establecidos (si los hubiera) del elemento padre, una entrada correspondiente se crea en el sistema de ficheros sysfs).

kobject_init Inicializa una kobject, es decir, establece el contador de referencias a su inicial valor e inicializa la lista de elementos del objeto.

kobect_add Inicializa un objeto del núcleo y la hace visible en sysfs.

kobject_cleanup Libera los recursos asignados cuando un kobject (y por lo tanto la

Page 22: Arquitectura del Kernel Linux

incrustación de objetos) ya no es necesario

La encapsulación en una estructura del valor único fue seleccionada para evitar la manipulación directa del valor. kref_init siempre debe ser utilizado para la inicialización. Si un objeto está en uso, se debe invocar kref_get de antemano para incrementar el contador de referencias. Decrementos kref_put el contador cuando el objeto no es ya no se utiliza.

5.14.2 Conjunto de objetos

En muchos casos, es necesario agrupar los diferentes objetos del núcleo en un conjunto, por ejemplo, el conjunto de todos dispositivos de caracteres o el conjunto de todos los dispositivos basados en PCI. La estructura de datos para este propósito es definen como sigue: <kobject.h>

struct kset {

struct kobj_type * ktype;

struct list_head list;

...

struct kobject kobj;

struct kset_uevent_ops *

uevent_ops;

};

Curiosamente, el kset sirve como el primer ejemplo de la utilización de objetos del Kernel. Dado que la gestión estructura de los conjuntos no es más que un objeto del kernel, se puede controlar a través del discutido previamente struct kobj. De hecho, una instancia está integrada a través de kobj. No tiene nada que ver con la recogida kobjects en el conjunto, pero sólo sirve para administrar las propiedades de la kset objeto mismo. Los demás miembros tienen el siguiente significado:

ktype puntos a un objeto, además, que

generaliza el comportamiento de la kset.

list se utiliza para crear una lista de todos

los objetos del kernel que son un miembro del conjunto.

uevent_ops proporciona punteros a los

métodos de varias funciones que retransmiten la información sobre el estado del conjunto de entorno de usuario. Este mecanismo es utilizado por el núcleo del modelo de controlador, por ejemplo, Mensajes formato que informan acerca de la adición de nuevos dispositivos.

Otra estructura se proporciona al grupo de características comunes de los objetos del núcleo. Se define de la siguiente manera: <kobject.h>

struct kobj_type { ... struct sysfs_ops sysfs_ops *; struct atributo ** default_attrs;

}; Tenga en cuenta que un kobj_type no se utiliza para recoger varios objetos del núcleo, esto ya está gestionado por ksets. En su lugar, proporciona una interfaz para el sistema de ficheros sysfs. Si varios objetos información de exportación similar a través del sistema de archivos, entonces esto puede ser simplificado mediante el uso de una única prestación de ktype los métodos necesarios.

5.14.3 Conteo de referencias

Recuento de referencia se utiliza para detectar la forma de un objeto en muchos lugares en el Kernel. Cada vez que una pate del Kernel necesita información contenida en un objeto, se incrementa el recuento de referencia, y cuando no necesita más la información, el recuento se decremento. Una vez que el recuento se ha reducido a 0, el Kernel sabe que el objeto no se requiere más, ya que es seguro para liberarlo de la memoria. El Kernel proporciona la estructura de datos siguiente para controlar el conteo de referencias: <kref.h>

struct kref {

atomic_t refcount;

};

La estructura de datos es muy simple ya que sólo proporciona una cuenta genérica, la referencia atómica. Atómica significa en este contexto que incrementar y decrementar la variable es también seguro de multiprocesador, donde más de un código de ruta pueden tener acceso a un objeto al mismo tiempo. El kref_init métodos auxiliares, kref_get y

kref_put se proporcionan para inicializar,

incremento o disminuir el contador de referencias. Esto podría parecer trivial a primera vista. Sin embargo, ayuda a evitar la duplicación de código excesivo, dado que cuenta con dicha referencia, junto con las mencionadas operaciones se utilizan en todo el Kernel. A pesar de la manipulación del contador de referencias de esta manera es seguro contra la concurrencia cuestiones, esto no implica que la

Page 23: Arquitectura del Kernel Linux

estructura de datos que rodean es seguro contra acceso concurrente, código del Kernel necesita emplear otros medios para garantizar que al acceder a estructuras de datos no causa ningún problema cuando esto puede ocurrir a partir de múltiples procesadores simultáneamente.

5.15 TIPOS DE DATOS

Algunas cuestiones relacionadas con los tipos de datos se manejan de manera diferente en el kernel en comparación con el entorno de usuario programas.

5.15.1 Definiciones de tipos

El núcleo utiliza typedef para definir distintos

tipos de datos con el fin de hacerse independiente de arquitectura específica y caracteristicas debido a la longitud diferente para los tipos de datos estándar en los procesadores individuales. Las definiciones tienen nombres tales como sector_t (para especificar un número de sector

en un dispositivo de bloque), pid_t (para indican

un identificador de proceso), y así sucesivamente, y se definen por el Kernel en el código de una arquitectura específica de tal una forma que se garantice que representan el rango de valores aplicable. Debido a que no suele ser importante saber en qué tipos de datos fundamentales de las definiciones se basan, y para simplificar, no siempre discutir las definiciones exactas de los tipos de datos en los siguientes capítulos. En su lugar, yo los uso sin más explicaciones - después de todo, son simplemente tipos estándar de datos compuestos no bajo otro nombre. Typedef’d las variables no se debe acceder

directamente, sino sólo a través de funciones auxiliares que introduzco cuando nos encontramos con el tipo. Esto se asegura de que estén manipulados, aunque la definición de tipo es transparente para el usuario. En ciertos puntos, el Kernel debe hacer uso de variables con un número exacto, claramente definido de bits por ejemplo, cuando las estructuras de datos necesitan ser almacenados en el disco duro. Para permitir el intercambio de datos entre distintos sistemas (por ejemplo, en memorias USB), su estructura externa mismo debe utilizarse siempre, independientemente de cómo los datos se representan internamente en el equipo. A tal efecto, el Kernel define varios tipos de datos enteros, que no sólo indican explícitamente si están firmados o no firmados, sino también especificar el número exacto de bits que

componen. __s8 __u8 y son, por ejemplo, los enteros 8-bits que son firmados (__s8) o sin signo (__u8). __u16 y __s16, y __u32 __s32 y __u64 __s64 y se definen de la misma manera.

5.15.2 Ordenación de Bytes

Para representar los números, las computadoras modernas utilizar el formato big endian o little endian. El formato indica cómo los tipos de datos de varios bytes se almacenan. Con orden big endian, el byte más significativo es almacenados en la dirección más baja y la importancia de los bytes disminuye a medida que el aumento de las direcciones. Con little endian pedidos, el byte menos significativo se almacena en la dirección más baja y la importancia de los bytes aumenta a medida que el aumento de las direcciones (algunas arquitecturas, como apoyo a las dos variantes MIPS). Figura 13 ilustra la cuestión.

Figura 13. El núcleo proporciona diversas funciones y macros para convertir el formato utilizado por la CPU y representaciones específicas: cpu_to_le64 convierte un tipo de 64-bit de datos en formato little endian, y le64_to_cpu hace lo contrario (si la arquitectura trabaja con el formato little endian, las rutinas son, por supuesto, tiene operadores; de lo contrario, las posiciones de bytes deben ser cambiados en consecuencia). Rutinas de conversión están disponibles para todos combinaciones de 64, 32 y 16 bits para formato big endian o little endian.

5.15.3 Variables por CPU

Una particularidad que no se produce en la programación del espacio de usuario normal es de variables por CPU. Son declarado con DEFINE_PER_CPU (nombre, tipo), donde name es el nombre de la variable y el tipo es el tipo de datos (Por ejemplo, int, estructura hash, etc.) En los sistemas con procesador único, esto no es

Page 24: Arquitectura del Kernel Linux

diferente de variables re declaración. En sistemas SMP con varias CPUs, una instancia de la variable se crea para cada CPU. El ejemplo, para una CPU en concreto se selecciona con get_cpu (nombre, unidad central de procesamiento), donde smp_processor_id (), que devuelve el identificador del procesador activo, se suele utilizar como argumento para la CPU. El empleo de variables por CPU tiene la ventaja de que los datos requeridos son más propensos a estar presentes en la caché de un procesador, por lo que se puede acceder con mayor rapidez. Este concepto también bordea varios problemas de comunicación que surgen cuando las variables con que se puede acceder por todas las CPU de un multiprocesador sistema.

5.15.4 El acceso a espacio de usuario En muchos puntos en el código fuente hay punteros __user etiquetados, los cuales son desconocidos en el espacio de usuario programación. El Kernel los utiliza para identificar a los punteros a las zonas en el espacio de usuario dirección que no puede ser de referencia, sin más precauciones. Esto es porque la memoria se asigna a través de tablas de páginas en la porción del espacio de usuario del espacio de direcciones virtuales y no directamente asignadas por la memoria física. Por lo tanto el Kernel tiene que garantizar que el marco de página en la memoria RAM que respalda el destino esté presente en realidad.

5.16 EVOLUCIÓN El desarrollo del kernel es un proceso muy dinámico, y la velocidad a la que el núcleo adquiere nuevas características y continúa mejorando a veces es poco menos que milagrosa. En un estudio realizado por el Linux Fundación ha puesto de manifiesto [KHCM], aproximadamente 10.000 parches van en cada nueva versión del núcleo, y esta enorme cantidad de código es creado por los desarrolladores de casi 1.000 por cada disparo. En promedio, 2,83 cambios están integrados cada hora, 24 horas al día y 7 días a la semana! Esto sólo puede resolverse con medios madura de la fuente código de gestión y comunicación entre los desarrolladores. La figura 14, que muestra el crecimiento de las fuentes del Kernel durante el último par de años.

Figura 14

6. ¿POR QUE KERNEL ES ESPECIAL?

El Kernel es un lugar increíble - pero después de todo, es sólo un programa en C grande con algunas partes en ensamblador. Entonces, ¿qué hace que el núcleo sea tan fascinante? Varios factores contribuyen a ello. En primer lugar, el Kernel está escrito por los mejores programadores del mundo, y eso se nota en el código. Es bien estructurada, escrita con una atención meticulosa a los detalles, y contiene soluciones inteligentes en todo el lugar. En una palabra: Es el código como debe ser. Sin embargo, esto no significa que el Kernel es el producto de una metodología de programación de libros de texto de estilo: A pesar de que emplea limpia abstracciones diseñado para mantener el código modular y manejable, es la mezcla con la otra cara del Kernel que hace que el código tan interesante y única: Si es necesario, el Kernel no alejado de ciertas reutilización de posiciones de bits de forma dependiente del contexto, la sobrecarga veces elementos de estructura múltiple, apretando otro de almacenamiento poco fuera de la parte de punteros alineados, utilizando libremente, y numerosas otras cosas que haría cualquier programador estructurado grito miserablemente en la agonía y el dolor.

Las técnicas que sería impensable en muchos libros de texto soluciones no sólo puede ser bueno, pero son simplemente necesarios para una adecuada del mundo real de trabajo del núcleo. Es el pequeño sendero que mantiene el equilibrio entre estos totalmente caras opuestas del núcleo que hace que todo el asunto tan interesante, desafiante y divertido.

Page 25: Arquitectura del Kernel Linux

Después de haber elogiado las fuentes del núcleo, hay una serie de cuestiones más sobria distinto del entorno de usuario programas:

❑ depurar el Kernel suele ser más difícil que la

depuración de los programas de espacio de usuario. Mientras que para el segundo una multitud de depuradores existentes, esto es mucho más difícil de lograr para el núcleo.

❑ El Kernel proporciona numerosas funciones

auxiliares que se asemejan a la biblioteca estándar de C se encuentra en espacio de usuario, pero las cosas son mucho más frugal en el dominio del núcleo. Errores en las aplicaciones de entorno de usuario.

❑ conducir a un fallo de segmentación o de un

volcado de memoria, pero los errores del Kernel se llevará a todo el sistema abajo. O, lo que es peor: Se mantendrá el núcleo feliz corriendo, pero se manifiestan en una hora extraña sistema después de la caída se produjo el error. Porque la depuración en el espacio del núcleo es más difícil que para los usos espacio de usuario como se mencionó anteriormente, es esencial que el código del Kernel recibe más atención y consideración prudente que el código entorno de usuario antes de que inicie su actividad.

❑ Se debe tener en cuenta que muchas

arquitecturas en el cual funciona el Kernel no admiten no alineados acceso a la memoria sin más trámite. Esto también afecta a la transferibilidad de las estructuras de datos porque a través de arquitecturas de relleno que se inserta por el compilador.

❑ Todo el código del Kernel deben estar

protegidos contra la concurrencia. Debido al apoyo de multiprocesador máquinas, el código del núcleo de Linux debe ser tanto entrante y seguro para subprocesos. Es decir, debe permitir que las rutinas se ejecuten de forma simultánea, y los datos deben estar protegidos contra el acceso paralelo.

❑ La mayoría de las arquitecturas no permiten

realizar cálculos de punto flotante en el Kernel, sin más preámbulos, lo que es necesario encontrar una manera de hacer sus cálculos con los tipos enteros.

7. CARACTERÍSTICAS

INTERESANTES DEL KERNEL

DE LINUX

Si la portabilidad y la eficiencia del kernel de Linux

fuera poco, también ofrecen otras características

que son nombradas a continuación.

El núcleo Linux es de código abierto, es un banco

de pruebas ideal para nuevos protocolos y los

avances de esos protocolos. Linux soporta una

gran cantidad de protocolos de red, incluyendo el

típico TCP / IP, así como la extensión de redes de

alta velocidad (más de 1 Gigabit Ethernet [GbE] y

10 GbE). Linux también soporta protocolos como

la Corriente del Protocolo de control de

transmisión (SCTP), que ofrece muchas

características avanzadas por encima de TCP

(como un protocolo que reemplaza TCP).

Linux también es un núcleo dinámico, ya que

permite la adición y la eliminación de

componentes de software estando en ejecución.

Éstos se llaman los módulos del kernel cargables

dinámicamente, y pueden ser insertados en el

arranque cuando se necesitan (cuando un

dispositivo en particular se encuentra, éste

requiere del llamado a este módulo) o en cualquier

momento por el usuario.

Un avance reciente de Linux es su uso como

sistema operativo para otros sistemas operativos

(llamado un hipervisor). Recientemente, se hizo

una modificación en el núcleo llamado Kernel

Virtual Machine (KVM). Esta modificación permitió

una nueva interfaz para el espacio de usuario que

permite a otros sistemas operativos correr por

encima del kernel KVM-habilitado. Además de

ejecutar otra instancia de Linux, Microsoft

Windows también pueden ser virtualizados. La

única restricción es que el procesador subyacente

debe ser compatible con las instrucciones de la

nueva virtualización.

Page 26: Arquitectura del Kernel Linux

8. LINUX: EL SISTEMA OPERATIVO DE LA INTERNET

Linux es un sistema de libre distribución para PCs. Es compatible con el estándar POSIX 1003.1 e incluye grandes áreas de funciones de Unix System V y BSD 4.3. Muchas partes substanciales del kernel de Linux sobre los cuales concierne esta serie de artículos fueron escritas por Linus Torvalds, un estudiante de ciencia de la computación en Finlandia. La primera versión del kernel de Linux vió la luz en Noviembre de 1991.

Características Principales

Linux satisface casi todas las demandas de un sistema operativo Unix actual:

Multitarea

Linux soporta multitarea verdadera, todos los procesos corren de manera independiente unos de otros. Ninguno de ellos necesita ceder el procesador para la ejecución de otros procesos.

Accesibilidad Multiusuario

Linux no sólo es un sistema operativo multiusuario. Sino que posee acceso multiusuario. Linux permite tener terminales conectadas al sistema utilizando los mismos recursos.

Ejecutables cargados en demanda

Solo aquellas partes del programa que son necesarias para la ejecución del mismo son cargadas en memoria.

Paginación

Puede ocurrir que la memoria esté totalmente ocupada. Linux entonces busca por páginas de memoria de 4k que puedan ser liberadas. Las páginas son almacenadas en disco y la memoria es liberada. Si alguna de estas páginas es requerida, Linux la toma del disco y la pone en su lugar original. A diferencia de lo que comúnmente se llama swapping (o archivo de intercambio para los usuarios de Microsoft Windows) sólo algunas páginas se guardan en disco. Los viejos sistemas Unix o inclusive los flamantes nuevos Windows 95 o NT escriben en disco todas las páginas de un proceso, lo cual es mucho menos eficiente.

Cache de disco dinámico

Los usuarios de MSDOS estarán familiarizados con SmartDrive (SMARTDRV). Este programa reserva una determinada zona de memoria fija para el cache del disco. Linux trabaja el cache del disco de una forma mucho más dinámica. La memoria de reserva para el disco se agranda cuando es necesario o se achica cuando hay escasez de memoria disponible.

Librerías compartidas

Las librerías son un conjunto de rutinas utilizadas por los programas para procesar datos. Hay un número de librerías estándares utilizadas por más de un proceso a la vez. En los viejos tiempos las librerías se incluían en el código ejecutable del programa. Así es que si uno o más programas utilizaban las mismas librerías estas eran cargadas más de una vez utilizando espacio en memoria innecesario. Aquí es donde las librerías compartidas entran en juego. Los ejecutables solo poseen un vínculo con la librería compartida. De esta manera si uno o más programas utilizan las mismas librerías éstas son cargadas sólo una vez.

Soporte para el estándar POSIX 1003.1 y en parte System V y BSD

POSIX 1003.1 define una interfaces mínima para un sistema operativo tipo Unix. Esta interface está descripta en declaración de funciones C. Este estardard es actualmente soportado por todos los recientes y relativamente sofisticados sistemas operativos. Microsoft Windows NT posee soporte para POSIX 1003.1. Linux 1.2 soporta POSIX en su totalidad. Algunas interfaces adicionales fueron y están siendo desarrolladas para compatibilidad con System V y BSD.

Diferentes formatos para archivos ejecutables

Quien no desea poder correr cualquier aplicación en Linux? Ya sea de DOS, Windows 95, FreeBSD o OS/2. Por esta razón emuladores de DOS y Windows95 están en actual desarrollo. Linux puede ejecutar binarios de otras plataformas Unix basadas en Intel que conformen con el estándar iBCS2,(intel Binary Compatibility standard).

Sistemas de archivos diferentes

Linux soporta una gran variedad de sistemas de archivos. El más usado actualmente es el Second Extended File System (Ext2). Otro sistema de archivos implementeado de la File Allocation Table

Page 27: Arquitectura del Kernel Linux

(FAT). Las restricciones de acceso a este sistema de archivos están dado para todo el disco ya que la FAT no está preparada para seguridad o acceso multiusuario.

Redes

Linux puede ser integrado en un sistema de redes Unix local. En principio todos los servicios de red son soportado, Network File System (NFS) y Remote Login (rlogin). SLIP y PPP ambos son soportados.

System V IPC

Linux usa esta tecnología para proveer de colas de mensajes, semáforos y memoria compartida. Estas son variantes clásicas de la comunicación entre-procesos (inter-process communication).

9. ¿DE DONDE VIENE KERNEL LINUX?

CONCLUSIONES

REFERENCIAS

[1] The GNU site describes the GNU GPL that

covers the Linux kernel and most of the useful

applications provided with it. Also described is a

less restrictive form of the GPL called the Lesser

GPL (LGPL).

[2] UNIX, MINIX and Linux are covered in

Wikipedia, along with a detailed family tree of the

operating systems.

[3] The GNU C Library, or glibc, is the implementation of the standard C library. It's used in the GNU/Linux operating system, as well as the GNU/Hurd microkernel operating system. "Kernel command using Linux system calls" (developerWorks, March 2007) covers the SCI, which is an important layer in the Linux kernel, with user-space support from glibc that enables function calls between user space and the kernel. "Discover the Linux Kernel Virtual Machine" (developerWorks, April 2007) covers the recent introduction of virtualization into the kernel, which turns the Linux kernel into a hypervisor for other virtualized operating systems.

[4] Michael Beck, Harald B¨ohme, Mirko Dziadzka, Ulrich Kunitz, Robert Magnus, and Dirk Verworrner. Linux-Kernelprogrammierung. Addison-Wesley, 2001. [5] Daniel P. Bovet and Marco Cesati. Understanding the Linux Kernel. O’Reilly, 3rd edition,2005.