Introducción a Linux/Arquitectura
Introducción
editarLa arquitectura interna de Linux es compleja pero se puede resumir las partes importantes de forma breve y fácil de entender.
Procesos
editarLinux se organiza en procesos, que son tareas independientes que se ejecutan de forma simultánea mientras el sistema está en funcionamiento. Los procesos cuelgan unos de otros en una dependencia padre/hijo. Inicialmente al arrancar el sistema sólo existe un proceso, llamado init. Init lee los ficheros de configuración de arranque presentes en el directorio /etc y va creando procesos hijos. Estos a su vez tendrán sus propios hijos formando un árbol de descendientes. Los procesos en ejecución se encuentran alojados en la memoria rápida RAM del sistema. Cuando se habla de ejecutar o lanzar o arrancar un proceso, nos estamos refiriendo al proceso de leer un fichero almacenado en el disco duro que contiene las instrucciones del programa, colocando las mismas en la memoria RAM y a continuación empezando a ejecutar las instrucciones del programa ya en RAM.
Usuarios
editarLinux está diseñado para ser utilizado por varios usuarios simultáneamente. Aun cuando el sistema sólo vaya a ser utilizado por un único usuario, como es el caso corriente hoy en día, en general internamente Linux utilizará varios usuarios 'robots' para organizar mejor y de forma más segura el sistema. Linux siempre tiene un superusuario llamado 'root' ('raíz' traducido). En el siguiente párrafo se explica por qué crea varios usuarios en vez de uno solo.
Cada uno de los procesos pertenece a un usuario y en función del usuario asociado, dicho proceso tendrá unos permisos u otros. Un proceso en ejecución puede cambiar su usuario asociado si tiene los permisos suficientes para hacerlo. En general sólo tendrá permisos para cambiar de usuario cuando el usuario actual asociado al proceso sea 'root'. El proceso inicial Init se ejecuta con el usuario asociado 'root' lo cual le confiere permisos totales sobre la máquina. En general cuando Init ejecute sus procesos hijos lo hará asociándolos a usuarios distintos cuyos permisos se reduzcan a los esenciales para ejecutar la tarea para la cual están diseñado. P.ej, Init puede arrancar un proceso 'servidor de correo' asociado al usuario 'mail'. Este usuario tendrá los permisos justos y necesarios para poder enviar y recibir correo y almacenarlo en el directorio /var/spool/mail. El proceso 'servicio de correo' puede a su vez arrancar procesos hijos pero estos estarán automáticamente asociados a su usuario 'mail', nunca a 'root'. Este simple sistema de permisos provee a Linux de un sistema de seguridad muy sólido.
El entorno gráfico estándar de Linux es un proceso más llamado X. Cuando se arrancan las X todos los programas gráficos (que son a su vez procesos) colgarán de él y se ejecutarán por normal general con los permisos del usuario que se ha logeado con su nombre y password al inicio de la sesión. Las aplicaciones que solemos manejar frecuentemente como el navegador web o el reproductor de vídeo no son más que procesos hijo del proceso X. Si ejecutamos por ejemplo un cliente de correo con un agujero de seguridad y descargamos un correo con virus, dicho virus 'engañará' al cliente de correo para que lo ejecute y entonces tendremos un nuevo proceso 'virus' colgando del cliente de correo y asociado al usuario que inició la sesión. Sin embargo puesto que este usuario no tiene permisos de administración el virus no podrá modificar ficheros claves del sistema, solamente los ficheros propios del usuario. Al reiniciar el ordenador el virus habrá desaparecido. Esto complica enormemente la creación de virus para Linux. El entorno gráfico X es un proceso más, sin ningún privilegio sobre cualquier otro. Esto significa que podemos prescindir del mismo si no nos hace falta. En general, cuando Linux se utiliza como servidor de Internet es normal no iniciar el entorno gráfico ya que consume mucha memoria y puede ralentizar el sistema. Esto ha hecho que Linux se popularice y desplaze a Windows en el entorno profesional, ya que por ejemplo permite contratar servicios de hospedaje virtual a precios mucho más reducidos que sus equivalentes en Windows. También, al no depender de un entorno gráfico, puede administrarse remotamente de forma mucho más cómoda mediante líneas de comandos, mientras que Windows requiere transmitir el entorno gráfico a través de Internet (mucho más lento, costoso e inseguro).
Ficheros
editarLos procesos acceden al hardware y a otros recursos como la conexión de red a internet o los datos almacenados en disco a través de un sistema de ficheros. Todas las entradas y salidas de datos desde/hacia procesos se realiza a través de ficheros. P.ej, para acceder a la tarjeta gráfica de vídeo lo hará leyendo y escribiendo en:
/dev/video/card0 ^ ^ ^ │ │ └── Tarjeta 0 (podría haber más de una tarjeta de video en el sistema) │ │ │ └── Subdirectorio/carpeta video │ └── Abreviatura de device (dispositivo)
Mientras que para acceder a un documento de texto almacenado en su disco duro lo hará accediendo a una ruta similar a:
/home/usuario1/documento1.odf ^ ^ ^ │ │ └── Documento que queremos leer/editar. │ │ │ └── Subdirectorio/carpeta usuario1 (puede haber muchos usuarios) │ └── Directorio reservado para los ficheros de los usuarios finales
En general un mismo proceso puede acceder simultáneamente a varios ficheros y a su vez un mismo fichero puede ser accedido simultáneamente por varios procesos como se vé en el esquema siguiente:
ARBOL DE PROCESOS FICHEROS Y DIRECTORIOS ========================================================================== procesoInicial(Init) /bin/Init │ ├── proc.Hijo1 ───────────────────▇───────────── /bin/proc.Hijo1 │ ├── proc.Hijo1.1 ──────────┼─▇─────────── /bin/proc.Hijo1.1 │ └── proc.Hijo1.2 ──────────┼─┼─▇───────── /bin/proc.Hijo1.2 ├── proc.Hijo2 ───────────────────┼─┼─┼─▇─────── /bin/proc.Hijo2 │ ├── proc.Hijo2.1 ──────────┼─┼─┼─┼─▇───── /bin/proc.Hijo2.1 │ └── proc.Hijo2.2 ──────────┼─┼─┼─┼─┼─▇─── /bin/proc.Hijo2.2 ├── proc.Hijo3 ───────────────────┼─┼─┼─┼─┼─┼─▇─ /bin/proc.Hijo3 │ └── proc.Hijo3.1 ──────────┼─┼─┼─┼─┼─┼─┼─ /bin/proc.Hijo3.1 │ └── proc.Hijo3.1.1┼─┼─┼─┼─┼─┼─┼─ /bin/proc.Hijo3.1.1 ├── proc.Hijo4 │ │ │ │ │ │ │ ... ... ▇─▇─▇─▇─▇─▇─▇─ / ▇─▇─▇─┼─┼─┼─┼─ /dev/pts/0 ┼─┼─┼─▇─▇─▇─┼─ /dev/pts/1 ┼─┼─┼─┼─┼─┼─┼─ /dev/pts/2 ┼─▇─┼─┼─▇─┼─┼─ /etc/passwd ┼─┼─▇─┼─┼─▇─┼─ /dev/snd/controlC0 ▇─▇─▇─▇─▇─▇─▇─ /dev/null ▇─┼─▇─┼─▇─▇─▇─ /lib/i686/libc-2.11.so ...
En el esquema anterior puede verse como por ejemplo todos los procesos (lado izquierdo) tienen acceso a '/', la raíz del sistema así como a /dev/null. Cada proceso tiene acceso también a su imagen en el disco duro desde donde se leen el mismo antes de volcarla a memoria RAM.
A continuación se muestra un ejemplo real del árbol de procesos hasta llegar al proceso navegador firefox:
USUARIO PROCESO root /sbin/init [5] ... root \_ /usr/sbin/gdm-binary usuario1 \_ /etc/X11/X usuario1 \_ gnome-panel usuario1 \_ /usr/bin/firefox
En el esquema anterior se puede observar como el proceso inicial init lanzará entre otros el proceso gdm-binary que es el encargado de autentificarnos con nuestro usuario y password. A continuación ejecutará el entorno gráfico X. Dentro de X se ejecutarán una serie de aplicaciones, p.ej, el reloj mostrando la hora o el administrador de archivos. En el esquema anterior se muestra solamente la aplicación gnome-panel, una pequeña barra colocada en el lateral del monitor y que sirve para que el usuario pueda indicarle al sistema qué otras tareas (procesos) quiere ejecutar a continuación pulsando sobre un icono gráfico asociado a la misma. En este caso se ejecutó él navegador web firefox. Como puede observarse en el esquema, firefox se ejecuta asociado al usuario1 y por tanto con los permisos restringidos del mismo, ya que es hijo de gnome-panel, que a su vez es hijo de X y que fue ejecutado como usuario1 por el gestor de sesiones una vez identificados correctamente con nuestro usuario y password. Si mientras navegamos por internet un virus se colase en nuestro navegador, entonces el esquema anterior quedaría como:
USUARIO PROCESO root /sbin/init [5] ... root \_ /usr/sbin/gdm-binary usuario1 \_ /etc/X11/X usuario1 \_ gnome-panel usuario1 \_ /usr/bin/firefox usuario1 \_ /home/usuario1/MiVirusFavorito
MiVirusFavorito estaría muy limitado y sólo podría acceder a ficheros del usuario1, es decir aquellos situados dentro de la carpeta /home/usuario1/. Puesto que no tiene acceso a los ficheros de arranque, si reiniciamos la máquina el virus morirá ya que 'init' jamás ejecutará el fichero /home/usuario1/MiVirusFavorito. Por otro lado, puesto que otras máquinas sólo permanecerán infectadas mientras el virus esté en funcionamiento, la posibilidad de que dicha máquina 'zoombie' nos ataque será muy reducida. Este sistema de seguridad no transforma a Linux en un sistema invencible pero sí mucho más complicado de infectar que otros sistemas operativos. Por tanto hay que procurar mantener actualizado el sistema y hacer copias de seguridad, aun cuando tengamos la certeza de que las posibilidades de ataque son muy inferiores.
Con esta pequeña introducción ya podemos curiosear las tripas de nuestro sistema. Para ello podemos utilizar los comandos de monitorización.
El kernel
editarComentaba anteriormente que el primer proceso en ejecutarse el init. En realidad esto no ha sido más que una mentira con fines pedagógicos. El primer proceso en ejecutarse es el Kernel. El kernel hace de frontera entre el software y el hardware. Para nuestra CPU, el kernel es un programa de software como cualquier otro (o casi como cualquier otro) pero para el resto de procesos, init incluido, el kernel se comporta como si fuese hardware. Cuando un proceso quiere acceder al hardware no lo hace directamente, sino que se lo pide al kernel. El kernel hace de interlocutor entre procesos y hardware. Si varios procesos quieren acceder al disco duro o a Internet, el kernel asignará un tiempo a cada uno de ellos, copiará los datos que cada proceso quiere enviar y los enviará al disco duro o a la red. También es el kernel el encargado de distribuir el tiempo de CPU asignado a cada proceso. Linux es un sistema multiproceso debido a que, aun disponiendo de un único procesador, Linux es capaz de ejecutar simultáneamente varias tareas haciendo rotar el propietario de la CPU cada fracción de segundo. En realidad puede asignar el control de la CPU a un nuevo proceso entre 100 o 1000 veces por segundo, dependiendo de la potencia de la CPU. Para un ser humano da la impresión de que todas las tareas se están ejecutando de forma simultánea. Este sistema de asignación de la CPU es clave y está extremadamente estudiado y optimizado. P.ej, Linux es lo suficientemente inteligente como para saber qué procesos están a la espera de recibir un dato de internet y, mientras este dato no llegue, no le asignará el valioso tiempo de CPU. Desde hace unos años a esta parte, los procesadores han desarrollado sistemas de ahorro de energía permitiendo disminuir la frecuencia, potencia o ciclo de trabajo de la CPU cuando no hay tareas que hacer. Linux está al tanto de este hecho y si observa que no hay aplicaciones demandando la CPU automáticamente le indica al procesador que disminuya el consumo de energía.
Si antes nombrábamos que los procesos están asociados a usuarios y gestionan ficheros, en realidad estos usuarios y ficheros son gestionados por el kernel. Cuando un proceso quiere acceder a un fichero, en realidad le pide al kernel que acceda al fichero y será el kernel quien le devuelva los datos que haya leido. Antes de ello el kernel comprueba el usuario y grupo asociado al proceso, comprueba a su vez los usuarios o grupos que pueden acceder a dicho fichero. Si no concuerdan, en vez de devolver el dato, devolverá un error o excepción al proceso llamante indicándole el "porque".
Otra labor del kernel es abstraer a los procesos del hardware real de la máquina. Un proceso 'visor de fotos' que quiera acceder al fichero /home/usuario1/FOTOS/vaciones001.png no tiene que preocuparse si dicho fichero está en un disco duro, una memoria SSD o debe ser accedido a través de la red local ya que se encuentra en otro ordenador. El kernel mediante un sistema llamado "montaje" mapea rutas lógicas de directorios, p.ej, /home/usuario1 con un dispositivo físico, p.ej, el disco duro local o un disco duro en Internet a 1000 kms. de distancia. El proceso 'visor de fotos' no se tiene que preocupar de dónde está fisicamente el fichero, sólamente de su ruta simbólica /home/usuario1/FOTOS/vacaciones0001.png.
La memoria RAM de un sistema es limitada, y de nuevo el kernel se encarga de asignar memoria a los procesos. Además, de nuevo, es lo suficientemente inteligente como para saber qué procesos llevan mucho tiempo sin ejecutarse (por ejemplo un servidor de correo que lleva 10 minutos sin enviar ni recibir correos) y si la memoria RAM escasea, es capaz de mover el proceso de RAM al disco duro y asignar la memoria RAM a procesos que en un instante dado puedan hacer mejor uso de la misma.