1. Introducción a los entornos de trabajo UNIX

1.4. Programas y procesos

Los ordenadores ejecutan programas que son listados de instrucciones que indican cómo procesar un conjunto de datos.

Podemos dividir los lenguajes de programación entre:

  • Bajo nivel: ensambladores y de máquina. Cercanos al código binario.
  • Alto nivel: fáciles de leer y entender (por ejemplo, C, PHP, Python o Java).

Así mismo podemos diferenciar los lenguajes de alto nivel compilados o interpretados.

Un programa escrito con un lenguaje de programación compilado, para poder ejecutarse, necesita ser antes procesado por un compilador adecuado, y traducido a lenguaje máquina (binario). Los compiladores son programas encargados de realizar el análisis léxico, sintáctico y semántico del código. Una vez superada esa etapa de verificación, el compilador genera un fichero objeto que debe ser enlazado con varias librerías de funciones del sistema para generar un fichero ejecutable binario. El usuario puede ejecutar este archivo cuando sea preciso. La depuración de los programas compilados es costosa, y es rentable solo en los casos en que el rendimiento óptimo de estos, en términos de tiempo de ejecución y espacio de memoria, es capital.

Para efectuar tareas más sencillas es posible diseñar prototipos (en inglés, scripts) empleando lenguajes orientados a la producción rápida de programas, como Perl o Python, lenguajes interpretados. Estos lenguajes de scripting poseen un juego de instrucciones específicamente diseñado para facilitar la adquisición y tratamiento de ficheros de texto. Sus intérpretes procesan los programas instrucción a instrucción, saltándose de ese modo la creación de un fichero binario. A cambio, su rendimiento, en comparación con los ficheros ejecutables, es menor.

Una vez el usuario decide ejecutar un programa, el SO debe crear una entidad lógica asociada a este código a la que dotar de recursos suficientes para desarrollar su actividad (procesador, memoria y acceso a dispositivos). Esta metodología permite ejecutar de forma concurrente varias instancias de la misma aplicación sin mayor inconveniente que los propios de la compartición de algunos recursos (fácilmente subsanables dentro del programa, utilizando nombres únicos para los ficheros y otros dispositivos).

Dado que solo un proceso puede estar simultáneamente en posesión de la CPU, debe realizarse una planificación óptima para decidir en cada momento a qué proceso le corresponde su uso. Pese a que la compartición del procesador parece una seria limitación, es en realidad una gran ventaja, pues un proceso gasta una fracción importante de su tiempo esperando para acceder a otros dispositivos más lentos. Por tanto, solapando el uso de la CPU con las esperas de los procesos, se consigue simular un trabajo en paralelo, cuando realmente solo existe un procesador.

Las estaciones de trabajo actuales están dotadas de multiprocesadores, esto es, nodos con dos, cuatro o más procesadores dentro de la misma máquina. Gracias a esta ampliación de los recursos disponibles, el SO, mediante las librerías de diseño de programas apropiadas, puede hacer trabajar sus programas en paralelo, permitiendo que determinados fragmentos de estos trabajen independientemente sobre distintos conjuntos de datos en diferentes procesadores. Cada unidad de código ejecutable en paralelo dentro del proceso recibe el nombre de hilo de ejecución (en inglés, thread). En un sistema con una única CPU, el SO también es capaz de planificar varios threads para simular paralelismo, siempre que la carga de trabajo de la máquina no sea excesiva.