Fundamentos de Sistemas Operativos Linux: Procesos, Shell Scripting y Comunicación IPC

I. Shell Scripting y Herramientas de Compilación

C1. Ejecución de Scripts Shell

Indica tres formas para conseguir que un archivo de texto ASCII se pueda ejecutar como un script de shell:

  1. Asegurando que el archivo tenga permisos de ejecución (`chmod +x script.sh`) y ejecutándolo directamente: linux~$ ./scriptshell.sh.
  2. Usando el comando source: linux~$ source scriptshell.sh.
  3. Usando el comando punto (.): linux~$ . scriptshell.sh.

C2. Evaluación en Cortocircuito en Shell Scripts

Las operaciones lógicas en un script de shell se evalúan en cortocircuito. Explica en qué consiste esto y pon un ejemplo.

C3. Uso e Información de los Ficheros «Makefile»

Este comando sirve para organizar la compilación y el enlazado de programas complicados que dependen de muchos módulos y librerías diferentes. Cuando se ejecuta este comando, se construye un nuevo ejecutable volviendo a compilar solo aquellos ficheros fuente que son más recientes que los ficheros compilados correspondientes, teniendo en cuenta para ello las fechas de última modificación de cada fichero.

Este comando se basa en un fichero ASCII (llamado por defecto makefile) que contiene una relación de dependencias entre los distintos módulos, así como las acciones que hay que realizar para poner a punto cada módulo, es decir, para pasar de un fuente a un objeto, por ejemplo. Este comando tiene la siguiente forma general:

    make [–f makefilename] [–arg_opt] [exe_name]

El fichero makefile (con este o con otro nombre invocado por medio de la opción –f) contiene cuatro tipos de líneas diferentes:

Tipos de Líneas en un Makefile

  • Líneas de comentario: Que comienzan por el carácter (#). Si en una línea cualquiera aparece el carácter (#), se ignora todo lo que aparece a continuación de dicho carácter en dicha línea.
  • Líneas de definición de macros: Tienen la forma general, IDENTIFICADOR = cadena_de_caracteres. Si en alguna otra línea aparece $(IDENTIFICADOR), dicha ocurrencia se sustituye por cadena_de_caracteres. No es necesario que el nombre del identificador esté escrito con mayúsculas, pero es una costumbre bastante extendida el hacerlo así. Mediante el uso de macros se pueden representar brevemente pathnames o listas de nombres de ficheros largos. Si el identificador tiene una sola letra, no hace falta poner los paréntesis. El comando make tiene una serie de macros definidas por defecto que se pueden listar con el comando make –p.
  • Líneas describiendo las relaciones de dependencia: Tienen la forma, file.o fila.o ... : file1.cpp file2.cpp ... La lista de ficheros que están a la izquierda del carácter (:) dependen de los ficheros que están a la derecha. En estas líneas se realiza la sustitución habitual de los caracteres (?*[]).
  • Líneas de comandos shell: Comenzando siempre por un tabulador. Estas líneas representan las acciones que hay que realizar para actualizar los ficheros dependientes, según las relaciones de dependencia descritas en la línea anterior. En una misma línea de comandos puede haber varios comandos separados por un carácter (;), y de este modo se ejecutan en un mismo proceso; si hay varias líneas de comandos, cada línea se ejecuta en un proceso diferente. Estos comandos shell (compilaciones, etc.) se ejecutan o no según las fechas de los ficheros correspondientes. Hay también una lista de dependencias implícitas y de macrodefiniciones estándar que se pueden obtener con el comando make -p (la salida de este comando puede tener varios cientos de líneas).

II. Gestión de Procesos y Señales en Linux

C1. Identificador de Proceso (PID)

Indica qué es un identificador de proceso y para qué se emplea en Linux.

Cada proceso en un sistema Linux se identifica por su identificador (ID) de proceso único, a veces conocido como PID. Los ID de proceso son números de 16 bits que se asignan secuencialmente a medida que se crean nuevos procesos.

C2. Visualización de Procesos Activos (`ps`)

¿Cómo puedo saber los procesos que están activos en Linux? ¿Qué tipo de información puedo conseguir?

El comando ps muestra los procesos que se ejecutan en el sistema. La versión de ps de GNU/Linux tiene una gran cantidad de opciones, ya que trata de ser compatible con versiones de ps de otras variantes de UNIX. Estas opciones controlan qué procesos se muestran y la información que se muestra para cada uno. De forma predeterminada, la ejecución de ps muestra los procesos controlados por la terminal o la ventana de terminal desde la que se invoca ps.

C3. La Función de Librería Estándar `system()`

Indica qué objetivo tiene y cómo funciona la función de la librería estándar system().

La función system() de la biblioteca estándar de C proporciona una manera fácil de ejecutar un comando desde un programa, de la misma manera que si el comando se hubiera escrito en un shell. De hecho, system() crea un subproceso que ejecuta el Bourne shell estándar (/bin/sh) y pasa el control al shell para su ejecución.

La función system() devuelve el valor de retorno del comando shell. Si el propio shell no se puede ejecutar, system() devuelve 127, y si se produce otro error, system() devuelve -1. Como la función system() utiliza un shell para ejecutar el comando, está sujeto a las características, limitaciones y fallos de seguridad del shell.

C4. Uso de la Familia de Funciones `exec`

Detalla para qué se emplea la función exec y pon algún ejemplo.

Las funciones exec reemplazan el programa que se ejecuta en un proceso con otro programa. Cuando un programa llama a una función exec, este proceso cesa inmediatamente la ejecución de ese programa y comienza a ejecutar un nuevo programa desde el principio, suponiendo que la llamada a exec no se encuentre con un error.

Como exec reemplaza el programa que inicia la llamada con otro, nunca retorna a menos que se produzca un error.

Dentro de la familia de funciones exec, hay funciones que varían ligeramente en sus capacidades y cómo se ejecutan.

Por ejemplo: Las funciones que contienen la letra p en sus nombres (execvp y execlp) aceptan un nombre de programa y buscan un programa con ese nombre en la ruta de ejecución actual. Las funciones que no contienen la p deben incluir la ruta completa del programa para ser ejecutado.

C5. Mecanismo de Señales en Linux

Explica en qué consiste el mecanismo de señales de Linux. ¿Cuáles son las señales más empleadas?

Las señales son mecanismos para comunicar y manipular los procesos en Linux.

Una señal es un mensaje especial enviado a un proceso. Las señales son asíncronas; cuando un proceso recibe una señal, procesa la señal de forma inmediata, sin terminar la función actual o incluso la línea actual de código.

Señales comunes incluyen:

  • SIGBUS (error de bus)
  • SIGSEGV (violación de segmentación)
  • SIGFPE (excepción de coma flotante)

Un uso común de este mecanismo es acabar con otro proceso mediante el envío de una señal SIGTERM o SIGKILL. Otro uso común es enviar un comando a un programa en ejecución. Están reservadas dos señales «definidas por el usuario» para este propósito: SIGUSR1 y SIGUSR2. La señal SIGHUP a veces se utiliza para este fin, comúnmente para despertar un programa ocioso o hacer que un programa vuelva a leer sus archivos de configuración.

C6. Señales de Terminación de Procesos

Enumera las señales empleadas para acabar con un proceso. Indica las diferencias entre ellas.

Un proceso también puede terminar de forma anormal, en respuesta a una señal. Por ejemplo, las señales mencionadas anteriormente SIGBUS, SIGSEGV, y SIGFPE hacen que el proceso termine. Se emplean otras señales para terminar un proceso de forma explícita:

  • SIGINT: Se envía a un proceso cuando el usuario intenta acabar con él tecleando Ctrl+C en la terminal.
  • SIGTERM: Es enviada con el comando kill.
  • SIGABRT: Un proceso se la envía a sí mismo al llamar a la función abort(), lo que termina el proceso y produce un fichero “core” para depuración.
  • SIGKILL: Es la señal de terminación más poderosa, que pone fin a un proceso de inmediato y no puede ser bloqueada o manipulada por el programa.

La disposición por defecto para SIGINT y SIGTERM es dar por terminado el proceso, pero pueden ser capturadas y manejadas por el programa, a diferencia de SIGKILL.

C7. Procesos Zombis

Indica cuándo se produce un proceso zombi y qué debemos hacer para evitarlo.

Un proceso zombi es un proceso que ha terminado, pero aún no ha sido limpiado. Un proceso zombi se produce cuando un proceso hijo termina y el proceso padre no está llamando a wait.

Podemos evitarlo haciendo que el proceso padre llame a wait3 o wait4 de forma periódica, para limpiar a los hijos zombis.

III. Comunicación Interprocesos (IPC) y Sockets

C1. Tipos de Comunicación entre Procesos (IPC) en Linux

Indica los tipos de comunicación de procesos que conoces y sus características más importantes.

En los sistemas LINUX podemos encontrar cinco tipos de comunicación entre procesos:

  • Memoria compartida: Permite a los procesos comunicarse con la simple lectura y escritura en una posición de memoria especificada.
  • Memoria asignada: Es similar a la memoria compartida, excepto que está asociado con un archivo en el sistema de ficheros.
  • Tuberías (Pipes): Permiten la comunicación secuencial de un proceso con otro proceso relacionado.
  • FIFO (Named Pipes): Son similares a las tuberías, excepto que permiten a procesos no relacionados comunicarse debido a que al tubo se le da un nombre en el sistema de archivos.
  • Sockets: Permiten la comunicación entre procesos locales o remotos a través de una red.

C2. Comunicación Padre-Hijo mediante Tuberías (`pipe`)

Indica los pasos a seguir para comunicar un proceso padre con su hijo a través de una tubería.

Una llamada a pipe crea los descriptores de archivos, que son válidos únicamente dentro de ese proceso y de sus hijos. Los descriptores de archivo de un proceso no se pueden pasar a procesos no relacionados. Sin embargo, cuando el proceso llama a fork, los descriptores de archivos se copian en el nuevo proceso hijo.

Una llamada a fork genera un proceso hijo. El hijo hereda los descriptores de archivo de la tubería. El padre escribe una cadena en la tubería, y el hijo lee por el otro extremo.

C3. Funciones `popen` y `pclose`

Explica cómo funcionan las funciones popen y pclose. Pon un ejemplo.

La llamada a popen crea un proceso hijo que ejecuta un comando (por ejemplo, sort), sustituyendo a las llamadas pipe, fork, dup2 y execlp. El segundo argumento, por ejemplo, "w", indica que este proceso quiere escribir en el proceso hijo. El valor de retorno de popen es un extremo del tubo, y el otro extremo está conectado a la entrada estándar del proceso hijo. Una vez finalizado el proceso de escritura, pclose cierra el flujo de datos del proceso hijo, espera a que el proceso termine, y devuelve su valor de estado.

C4. Espacios de Nombres de Socket

Un espacio de nombres de socket especifica cómo se escriben las direcciones de socket. Indica los espacios de nombres más empleados y qué tipo de comunicación soportan.

C5. Conexión Cliente-Servidor mediante Sockets

Indica los pasos que tiene que realizar un cliente para efectuar una conexión con un servidor. ¿Qué funciones emplea?

Para crear una conexión entre dos sockets, el cliente llama a connect, especificando la dirección de un socket de servidor al que conectarse. Un cliente es el proceso que inicia la conexión, y un servidor es el proceso que espera para aceptar conexiones. El cliente llama a connect para iniciar una conexión desde un socket local al socket del servidor especificado por el segundo argumento. El tercer argumento es la longitud, en bytes, de la estructura de la dirección apuntada por el segundo argumento. Los formatos de dirección de socket difieren de acuerdo con el espacio de nombres de socket que se emplee.

C6. Capacidad de un Servidor para Múltiples Peticiones

¿Un servidor puede atender más de una petición? Razona la respuesta.

Sí.

C7. Sockets Locales (UNIX) vs. Sockets de Internet (PF_INET)

Indica la diferencia entre sockets locales y sockets de internet. ¿Para qué se emplea cada uno?

Los sockets locales de dominio UNIX solo se pueden utilizar para comunicación entre dos procesos en un mismo equipo. Los sockets de dominio de internet, por otra parte, pueden ser utilizados para conectar los procesos de diferentes máquinas conectadas por una red de computadores.

Los sockets que conectan procesos en el mismo equipo pueden utilizar el espacio de nombres local, representado por los sinónimos PF_LOCAL y PF_UNIX. Son los llamados sockets locales o sockets de dominio UNIX. Sus direcciones de sockets, especificadas mediante nombres de archivos, solo se utilizan cuando se crean conexiones.

Los sockets que conectan procesos a través de internet utilizan el espacio de nombres de internet representado por PF_INET. Los protocolos más comunes son los basados en TCP/IP. El Protocolo de Internet (IP) es un protocolo de bajo nivel, que mueve los paquetes a través de internet, se encarga de dividir y volver a unir los paquetes, si es necesario. Solo garantiza la entrega con una política de ‘mejor esfuerzo’, por lo que los paquetes pueden desaparecer o ser reordenados durante el transporte. Cada equipo participante se especifica mediante una dirección IP única. El Protocolo de Control de Transmisión (TCP), que reside en la parte superior de la capa IP, ofrece conexiones de transporte fiables y ordenadas. Permite establecer comunicaciones orientadas a la conexión entre ordenadores y asegura que la información se entrega de forma fiable y en orden.

C8. Obtención de Dirección IP a partir de Nombre de Host (`gethostbyname`)

Explica cómo se puede obtener una dirección IP a partir de un nombre de host. ¿Qué función se emplea para esta tarea?

Para convertir nombres de host legibles por los humanos, ya sean números en notación estándar de punto (por ejemplo, 10.0.0.1) o nombres DNS (como www.codesourcery.com) en direcciones IP de 32 bits, podemos emplear la función gethostbyname.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.