*NIX y Linux, detalles de la arquitectura

Hemos estado hablando, en un artículo anterior, sobre la programación en C en general, sus estándares y ventajas. En esta oportunidad introduciremos tópicos sobre la programación C específica para sistemas *nix, Unix y derivados, como Linux 🙂


*nix: Unix y Linux

Unix es un sistema operativo creado en los laboratorios AT&T Bell por Ken Thompson y Dennis Ritche entre otros, a fines de los años 60.

Recordemos que Ritche fue también el programador que creó, junto con Kernighan, el lenguaje de programación C, y juntos escribieron “The C Programming Language“, el libro en el que explican su sintaxis y estructuras.

Unix es, en fin, el precursor de todos los sistemas Linux y derivados, y por supuesto, el padre de todas las variantes de Unix disponibles en la actualidad (Solaris, BSD, …).

En la siguiente imagen podemos ver una cronología de desarrollo de versiones de Unix, entre las que se encuentra Linux, por supuesto. A todos estos sistemas se los conoce, en general, como sistemas operativos *nix.

*nix

C y *nix

Todos los sistemas *nix están programados, en su mayor parte, por código C. Linux deriva de Unix, por lo que está mayormente programado en C también, junto con algunos segmentos de código C++ (la variante orientada a objetos de C) y lenguajes de scripting.

Linux en sí es el kernel del sistema operativo GNU en distribuciones GNU/Linux. GNU también está escrito en C en su mayor parte. Por lo general las aplicaciones que encontramos para Linux también están escritas en C o C++. El kernel, como hemos dicho tiene su mayor parte de código C, y controladores de bajo nivel escritos en lenguaje ensamblador.

El kernel del sistema operativo implementa muchos de los mecanismos originales utilizados por Unix para llevar a cabo sus tareas, y por supuesto, es código abierto, e incluso nosotros como programadores podemos escribir código utilizando estos mecanismos.

El kernel Linux

El kernel de un sistema operativo tiene muchas tareas específicas, que pueden englobarse generalmente en las siguientes:

Gestión de procesos

La administración de procesos hace referencia a cómo le kernel planificará los procesos en el procesador, cómo administrará las colas de procesos listos, en ejecución, esperando algún evento de entrada/salida, interrumpidos esperando alguna señal, etc.

Linux es, como Unix, un sistema operativo multitarea, por lo que puede ejecutar varios procesos simultáneamente. Para lograr este cometido, Linux arma una cola de procesos listos para entrar al procesador de la máquina, o a algún core libre del mismo. Determinar qué proceso de dicha lista será el siguiente en ocupar el recurso es tarea del planificador de procesos del kernel. El planificador determina ésto mediante un manejo de prioridades de tiempo real y de usuario, y una serie de bonus para evitar que un proceso de menor prioridad se mantenga fuera de ejecución por demasiado tiempo.

Gestión de memoria

La administración de memoria se refiere a cómo el kernel gestionará la memoria principal del sistema, qué mecanismo implementará, memoria paginada, memoria segmentada, combinación de paginación y segmentación, administración de espacios de intercambio y memoria virtual, administración de segmentos de memoria compartida entre procesos, direcciones de memoria de nivel de usuario y de nivel de núcleo, etc.

Gestión de Entrada/salida

La gestión de entrada/salida hace referencia a cómo el kernel llevará a cabo tareas de comunicación con dispositivos externos, o periféricos, tales como teclados, mouses, o dispositivos de almacenamiento.

Gestión de red

La gestión de red podría considerarse un mecanismo de entrada/salida, pero la mayor parte de los sistemas operativos generalmente lo implementan en forma separada, como una tarea de comunicación de datos con equipos remotos independiente. Aquí tenemos también la administración de múltiples direcciones por interfaz de red (ip aliassing), administración de firewalls y filtrado a nivel de capa de red, y gestión de redes privadas virtuales soportadas por ip (IPSec).

Gestión de IPC

La gestión de IPC, o mecanismos de comunicación entre procesos (Inter Process Communication) es una serie de herramientas que utiliza el kernel para establecer intercambios de datos y señalización entre procesos en el sistema operativo. Este es uno de los puntos importantes a destacar cuando decidimos incursionar en la programación *nix.

La arquitectura general de un *nix

En general, la arquitectura de un sistema operativo está dada por la siguiente figura.

so_layer *nix

En ella podemos apreciar que un sistema operativo puede dividirse en diferentes capas. La capa superior, en la que trabaja el usuario final, es la que contiene las aplicaciones instaladas. Debajo de las aplicaciones encontramos la capa de software de sistema, que contiene herramientas de desarrollo y API’s de medio/bajo nivel para el acceso a los recursos del sistema operativo. Debajo de esta capa encontramos directamente el sistema operativo. El sistema operativo oficia de interfaz entre el kernel y el entorno de usuario final.

Dentro del sistema operativo como concepto general encontramos al kernel. Lo correcto es considerar al kernel una pieza totalmente aislada del sistema, puesto que tienen funcionalidades y objetivos diferentes. El kernel se encarga de dar acceso a los recursos de hardware al sistema operativo. El kernel mantiene una serie de controladores y módulos de dispositivos que le permiten al sistema operativo, y por consiguiente, a las aplicaciones de usuario, acceder a los dispositivos de hardware.

Existe una capa que separa al kernel del resto del sistema, llamada Interfaz de llamadas al sistema, o SysCall Interface. La syscall es una API, o interfaz de programación que ofrece al sistema, y por consiguiente, a todo programador de sistemas operativos, o de utilidades para el mismo, funciones de acceso de medio y bajo nivel a las rutinas del kernel.

Esto le permite al programador administrar sus procesos, memoria, y mecanismos de comunicación, de una manera eficiente, logrando que las utilidades y herramientas disponibles brinden una excelente flexibilidad y un enorme espectro de posibilidades.

Organización del kernel Linux

El kernel Linux divide el espacio de direccionamiento en dos. Uno es el modo usuario, en el que corren aplicaciones de usuario y bibliotecas de C, como el imprescindible componente de un sistema GNU/Linux, libc.

En el modo kernel corre todo el kernel del sistema, y ésto se debe a que Linux es un sistema de arquitectura monolítica. En el espacio del núcleo encontramos los administradores de los que hemos estado hablando más arriba, como el planificador de procesos, el gestor de memoria, y los administradores de entrada/salida, redes, y sistema de archivos virtual.

En el modo núcleo también se encuentran los controladores de dispositivos y los módulos de administración de hardware.

Todo este kernel, como vimos, corre sobre el hardware del equipo, y lo administra de una manera extremadamente eficiente.

En la siguiente figura podemos ver una relación entre los diferentes componentes del kernel Linux, sus comunicaciones, y su organización dentro de la arquitectura de un sistema operativo.

lin_ker_arch *nix

Conclusiones

Hemos introducido conceptos fundamentales de sistemas operativos Unix, en particular, detalles de la administración y organización interna de Linux, para de esta forma tener una visión más cercana al funcionamiento y relaciones entre componentes.

Si te interesa la programación C en medio y bajo nivel, para poder administrar procesos y su comunicación, específicamente, el uso de herramientas de IPC para el programador de software de base, te recomiendo leer IPC: Comunicación entre procesos en *nix

Hasta la próxima!