Este documento presenta todos los apuntes (que confeccioné en su día) de la asignatura Sistemas Informáticos en Tiempo Real de 2º de Ing. industrial de la UMH impartida por Luis Miguel Jiménez y Rafael Puerto.
En esta asignatura aprendí la arquitectura básica de un Sistema Operativo en Tiempo Real, justificando su importancia en las aplicaciones de ingeniería.
En esta asignatura también se describen y analizan los elementos que conforman un sistema distribuido, justificando su importancia en aplicaciones industriales.
Además, se nos enseñó cómo emplear herramientas para el desarrollo aplicaciones de tiempo real (UNIX/POSIX).
En el siguiente enlace podés acceder a los datos del libro de la asignatura:
http://zbiblio.umh.es/uhtbin/cgisirsi/0/UMH/0/5?searchdata1=^C39987
1. 1. Sistemas Informáticos de Tiempo Real 1
1.1. Definición 1
1.2. Tiempo Real VS Rapidez 1
1.3. Sistemas Informáticos de Tiempo Real y Sistemas Empotrados 1
1.4. Sistemas Informáticos de Tiempo Real Estrictos y No Estrictos 2
1.5. Tolerancia a Fallos 3
1.6. Sistemas Controlados por Eventos o por Tiempo 4
2. Ejemplos de Sistemas Informáticos de Tiempo Real 4
3. Características de los Sistemas Informáticos de Tiempo Real 5
3.1. Grandes y Complejos 5
3.2. Manipulación de Magnitudes Físicas 5
3.3. Extremadamente Fiables y Seguros 5
3.4. Concurrencia 6
3.5. Herramientas de Manejo en Tiempo Real 6
3.6. Implementación Eficiente 7
3.7. Lenguajes de Programación 7
2. Sistemas Informáticos en Tiempo Real Tema I
1. Sistemas Informáticos de Tiempo Real.
1.1. Definición.
Se trata de aquellos sistemas capaces de captar estímulos generados por
el entorno y dar una respuesta a éstos en un periodo de tiempo finito
especificado.
Se puede observar que en la definición se destacan dos aspectos que
definen y diferencian los Sistemas Informáticos de Tiempo Real de los demás:
• Tiempo de respuesta: Es un aspecto clave ya que “no importa que
sea capaz de generar la respuesta correcta sino que ésta se
produzca en un tiempo determinado”.
Por ejemplo, de nada sirve un airbag si éste se pone en
funcionamiento después de un choque.
• Lógica de respuesta: El sistema debe interactuar con el entorno
adquiriendo estímulos y estados de entorno, y generando una
acción sobre dicho entorno.
Estas dos características provocan que el Sistema Informático de Tiempo
Real deba tener un comportamiento general a expensas de los eventos que
ocurran. Esta es la dificultad de los Sistemas Informáticos de Tiempo Real
puesto que para ello debemos hacer que los componentes trabajen juntos ante
la aparición de eventos no predecibles, fallos...
1.2. Tiempo Real VS Rapidez.
Generalmente, se confunden los términos de Sistema Informático de
Tiempo Real y sistema rápido. Todos los programas deben ser lo
suficientemente rápidos como para cumplir los requisitos de los usuarios, pero
el hecho de que un programa sea rápido no significa que sea de tiempo real.
Tiempo real significa trabajar con la distribución física de los
componentes, con el manejo de estímulos impredecibles, con fallos en los
componentes, con la incertidumbre acerca del entorno y con el rendimiento y
robustez del sistema. Un Sistema Informático de Tiempo Real debe ser lo
suficientemente rápido, pero es sólo una parte a tener en cuenta.
1.3. Sistemas Informáticos de Tiempo Real y Sistemas Empotrados.
Para conseguir el propósito para el cual se ha diseñado un Sistema
Informático de Tiempo Real, los componentes interactúan entre sí y con el
entorno intercambiando información y compartiendo recursos, modificando su
comportamiento.
1
Tema I Introducción a los SISTEMAS INFORMÁTICOSDE TIEMPO REAL
3. Sistemas Informáticos en Tiempo Real Tema I
El entorno lo podemos descomponer en dos partes:
• El entorno activo es donde se engloban los operadores que
intervienen en el comportamiento del sistema modificando el
modo de operación.
• El entorno pasivo comprende a los usuarios interesados solamente
en el servicio proporcionado, y al ambiente exterior que no tiene
nada que ver con la existencia del sistema.
Los sistemas empotrados son aquellos que no precisan de un entorno
activo. Además, existen otros sistemas considerados sistemas empotrados.
Estos son los subsistemas que forman parte de un sistema ya que no es posible
una intervención directa del operador y la funcionalidad debe ser soportada
completamente desde su interior.
1.4. Sistemas Informáticos de Tiempo Real Estrictos y No Estrictos.
En los Sistemas Informáticos de Tiempo Real se requiere tanto que el
resultado sea correcto como que se genere en un tiempo determinado. Con
respecto a la corrección lógica podemos decir que suele expresarse en términos
de salidas y entradas correctas.
En función de la importancia que se le de a la corrección temporal en un
Sistema Informático de Tiempo Real se puede realizar la siguiente clasificación:
• SISTEMAS ESTRICTOS: Son aquellos sistemas en los que el
tiempo es tan importante que no puede ser sacrificado por una
mejora en otros aspectos. En algunos sistemas, la corrección
temporal llega a ser tan crítica, es decir, tan importante, que la
corrección lógica puede ser relajada en aras de alcanzar un
tiempo de respuesta determinado. Por ejemplo, el chequeo de la
altitud de una aeronave automática en tiempos prescritos puede
tener consecuencias catastróficas a no ser que la respuesta llegue
aunque sea de mala calidad.
• SISTEMAS NO ESTRICTOS: En este caso, la corrección temporal
ya no es un aspecto crítico. Si se produce un fallo provocando un
retardo en la llegada de información, éste no provoca
consecuencias serias en el funcionamiento general del sistema.
Las tareas catalogadas como no estrictas se ejecutarán lo más
rápido que sea posible, pero sin estar forzadas por tiempos
límites, pudiendo ser sacrificada la corrección temporal bajo
ciertas circunstancias.
2
Tema I Introducción a los SISTEMAS INFORMÁTICOSDE TIEMPO REAL
4. Sistemas Informáticos en Tiempo Real Tema I
En general, un sistema puede estar constituido por una combinación de
tareas de ambos tipos mediante una jerarquía de prioridades y permitiendo la
relajación temporal de aquellas tareas que lo permitan. O también puede estar
formado por tareas con tiempos estrictos y no estrictos a la vez, es decir, la
respuesta a un evento puede tener un tiempo límite no estricto de 50 ms (para
asegurar un funcionamiento óptimo) y uno estricto de 200 ms (para evitar
posibles daños a los usuarios o al funcionamiento del sistema). Cada vez que
pasa tiempo se produce una pérdida general de la calidad de la información.
A sí mismo, se pueden definir dos tipos de relajación temporal:
• Si no se cumple el tiempo límite la información pierde
completamente su valor. En tareas periódicas puede ser admisible que se
pierda la ejecución de alguna de ellas.
• Puede ocurrir que el servicio llegue tarde pero éste sea válido para
una cierto intervalo de tiempo.
ESTRICTO NO ESTRICTO
Impone un tiempo de respuesta determinista. Impone un tiempo de respuesta pero no determinista.
En caso de sobrecarga no se degrada la respuesta En caso de sobrecarga se degrada la respuesta.
Trabaja con volúmenes de datos pequeños Trabaja con volúmenes de datos grandes.
1.5. Tolerancia a Fallos.
A pesar de que los sistemas están diseñados para que generen un
resultado correcto y dentro de un intervalo determinado, éstos pueden fallar
exhibiendo así un comportamiento para el cual no fueron diseñados. Ya que los
fallos son inevitables, un sistema debe ser robusto frente a ellos, es decir, debe
presentar un comportamiento de “tolerancia a fallos”.
En función del comportamiento en caso de fallo, los sistemas se pueden
clasificar como:
• SISTEMAS CON PARADA SEGURA: En caso de fallo se coloca al
sistema en un estado seguro de parada. Son aquellos en los
cuales un error puede tener consecuencias catastróficas.
• SISTEMAS CON DEGRADACIÓN ACEPTABLE: En caso de fallo,
presentan un funcionamiento parcial con pérdida de funcionalidad
o prestaciones, aunque el sistema puede seguir funcionando a
pesar de esa merma.
3
Tema I Introducción a los SISTEMAS INFORMÁTICOSDE TIEMPO REAL
5. Sistemas Informáticos en Tiempo Real Tema I
1.6. Sistemas Controlados por Eventos o por Tiempo.
Otra clasificación está basada en el uso de eventos o de ciclos de reloj
como controlador de la ejecución de las diversas tareas. Existen dos tipos:
• ARQUITECTURA CONTROLADA POR EVENTOS (“event-driven” o
“interrupt-driven”): Se establece la ejecución de un componente
basándose en la aparición de una interrupción o señal generada
por un evento externo.
Por ejemplo, un robot móvil que se mueve por el espacio
ante la aparición de un obstáculo ejecuta la tarea de evitarlo que
hasta entonces estaba dormida.
• ARQUITECTURA CONTROLADA POR TIEMPO (“time-driven”):
Opera tratando los pulsos regulares del reloj como si fueran
señales de interrupción. Cuando el reloj alcanza ciertos valores
predefinidos, una acción apropiada es seleccionada para su
ejecución.
Ambos tipos de arquitectura tienen sus ventajas y sus desventajas. Los
sistemas manejados por tiempo son más sencillos y robustos puesto que
permiten interfaces entre subsistemas muy controlados y con un
funcionamiento independiente mientras que los sistemas basados en
interrupciones son sistemas más eficaces para responder a eventos externos no
regulares.
2. Ejemplos de Sistemas Informáticos de Tiempo Real.
Robótica:
Los robots son vehículos que
se desplazan por un espacio de
trabajo y que interactúan con el
entorno. El seguimiento de
trayectorias, la planificación de
trayectorias libres de obstáculos y
seguimientos de blancos, son tareas
que deben responder ante ciertos
estímulos en un periodo de tiempo. Figura 1.1. Aplicaciones de control de robots
Automoción:
La industria del automóvil ha cambiado de tal manera que los sistemas
que antes se basaban totalmente en conceptos mecánicos, hoy en día han
pasado a un estado donde los componentes electrónicos juegan un papel muy
importante. Sistemas como el de inyección electrónica, el de control de
encendido o el de antibloqueo tienen al computador como un elemento que
debe reaccionar en tiempo real ante eventos generados por el entorno.
4
Tema I Introducción a los SISTEMAS INFORMÁTICOSDE TIEMPO REAL
6. Sistemas Informáticos en Tiempo Real Tema I
Por ejemplo, la centralita de inyección debe
mostrar variables de velocidad, aceleraciones,
revoluciones y temperatura para determinar la
inyección de combustible óptima.
El sistema antibloqueo de frenos controla la
velocidad de cada rueda y las aceleraciones para
regular la presión adecuada sobre los discos de
Figura 1.2. Sistema de control
de encendido de un automóvil
freno para evitar el bloqueo y minimizar la
distancia de frenado.
3. Características de los Sistemas Informáticos de Tiempo Real.
3.1. Grandes y Complejos.
Escribir pequeños programas no presenta ninguna complejidad pudiendo
hacerlo una sola persona la mismo tiempo que no es muy complicado que otra
persona sea capaz de comprender su diseño y funcionamiento. Por eso se dice
que los pequeños programas se escriben de forma casi artesanal. A pesar de
esto, se deben seguir ciertas normas de diseño y codificación: BUEN ESTILO.
Para referirnos al término grande, usaremos la palabra variedad, es
decir, si un sistema es grande se dice que tiene mucha variedad. La variedad
puede ser las necesidades y actividades del mundo real que se reflejan en el
funcionamiento del programa. Puesto que la naturaleza está cambiando
constantemente, los programas que exhiben una gran variedad deben cambiar
también.
Puesto que los Sistemas Informáticos de Tiempo Real deben responder
ante eventos, deben ser grandes y complejos para poder atender cualquier tipo
de evento.
3.2. Manipulación de Magnitudes Físicas.
Sabemos que un Sistema Informático de Tiempo Real debe controlar
actividades del entorno mediante captura o activación de variables físicas.
Las señales físicas suelen ser analógicas por lo que deben ser
convertidas a información digital manejable por el computador. Para la captura
de señales se requiere un muestreo (adquisición de valores) y una
cuantificación (codificación en niveles). El período de muestreo (intervalo de
tiempo transcurrido entre dos capturas sucesivas) depende del tipo de señal.
3.3. Extremadamente Fiable y Seguro.
Es necesario tener como directriz para el diseño de Sistemas
Informáticos de Tiempo Real la FIABILIDAD y la SEGURIDAD, ya que muchos
controlan funciones vitales.
5
Tema I Introducción a los SISTEMAS INFORMÁTICOSDE TIEMPO REAL
7. Sistemas Informáticos en Tiempo Real Tema I
Un fallo en el generador de energía eléctrica que suministra la unidad de
cuidados intensivos puede ser catastrófico.
Un error del controlador de una planta química puede provocar daños
graves en los equipos o en el medio ambiente.
Esto nos dice que tanto el hardware como el software que operan en
estos sistemas deben ser extremadamente fiables y seguros. Tienen en cuenta
hasta el posible error humano.
3.4. Concurrencia.
Se trata de capacidad de un sistema para mantener varias tareas en
estados intermedios de ejecución. Puesto que pueden ocurrir dos o más
eventos de forma paralela, nuestro Sistema Informático de Tiempo Real debe
tener la capacidad de atenderlos de forma paralela.
SISTEMAS DE TIEMPO COMPARTIDO: Se trata de aquellos sistemas que,
por tener sólo una CPU, no pueden realizar tareas simultáneamente pero
pueden mantener varias tareas en un punto intermedio de ejecución,
ejecutando de forma alternativa.
SISTEMAS MULTIPROCESADORES: Permiten la ejecución de tareas de
forma simultánea de forma paralela.
SISTEMAS DISTRIBUIDOS: Permite el paralelismo y los computadores se
encuentran interconectados y geográficamente dispersos.
Debido a las dificultades y problemas que entraña permitir a un
programador que cree programas para sistemas con carácter concurrente se ha
optado por emplear otras herramientas de trabajo como las que aportan
lenguajes como Occam o ADA95 o por sistemas operativos como UNIX.
3.5. Herramientas de Manejo en Tiempo Real.
Es muy difícil diseñar sistemas que garanticen una respuesta apropiada
en el tiempo apropiado para toda condición. Por eso, los Sistemas Informáticos
de Tiempo Real se construyen con ciertos márgenes sobrantes, de modo que
este no produzca retardos en los períodos críticos ni en el peor de los casos.
Es preciso que se disponga de un soporte que permita:
- Especificar el tiempo de ejecución de cada tarea.
- Especificar el tiempo de finalización de cada tarea.
- Responder a situaciones donde no se cumplen los requerimientos
temporales.
- Responder a situaciones donde los experimentos temporales no
varíen.
6
Tema I Introducción a los SISTEMAS INFORMÁTICOSDE TIEMPO REAL
8. Sistemas Informáticos en Tiempo Real Tema I
3.6. Implementación Eficiente.
La eficiencia debe ser un objetivo en los Sistemas Informáticos de
Tiempo Real.
3.7. Lenguajes de Programación.
Lenguaje ensamblador:
• Muy Eficiente
• Difícil de implementar la concurrencia.
Lenguajes secuenciales de alto nivel:
• C, C++, Java, Pascal, Fortran, Jovial, Coral, RTL/2.
• Portables, y fáciles de programar.
• Lo incorporan soporte para la concurrencia (debe ser soportado
por el S.O.).
Lenguajes concurrentes de alto nivel:
• ADA95, Modula-2, PEARL, Mesa, CHILL.
• Soprte de la concurrencia y especificaciones temporales en el
propio lenguaje.
Comportamiento
Temporal
Modelo del Entorno
Descomposición
Abstracción
Diseño Especificación de
General requerimientos
Diseño
de Detalle
Implementación
Métodos de Prototipos
Formales
Implementación
Final Verificación
Test del
Prototipo
Figura 1.3. Fases en el diseño de una aplicación
7
Tema I Introducción a los SISTEMAS INFORMÁTICOSDE TIEMPO REAL
19. 1. Introducción 1
2. Procesos 1
2.1. Definición y propiedades 1
2.2. Estados de un proceso 2
2.3. Información adicional sobre los procesos 3
2.4. Creación y terminación de procesos 4
i) Creación de Procesos 4
ii) Terminación de Procesos 5
3. Threads 5
3.1. Ventajas de Trabajar con Threads 7
3.2. Inconvenientes de Trabajar con Threads 7
3.3. Modelos de Control de Threads 7
i) A Nivel de Usuario 7
ii) A Nivel de Núcleo 8
iii) A Nivel Híbrido 9
20. Sistemas Informáticos en Tiempo Real Tema II
1. Introducción.
Un sistema operativo potente (todos los Sistemas Operativos de Tiempo
Real) es aquel capaz de ejercer más de una tarea en el mismo instante de
tiempo, es decir, debe ser capaz de realizar tareas de forma concurrente.
Por ejemplo, un sistema operativo multitarea debe ser capaz de ejecutar
un programa del usuario al mismo tiempo que lee del disco o imprime un
documento.
Pueden existir varios mecanismos para conseguir que un Sistema
Operativo cumpla esta característica. Nosotros explicaremos dos:
• PARALELISMO:
Se trata de un método para que un Sistema Operativo pueda realizar
varias tareas haciendo uso de varios computadores. Los ordenadores se
conectan entre sí de modo que cada uno puede estar realizando una tarea
totalmente distinta a las que se ejecutan por los otros ordenadores, es decir,
cada computador realiza una tarea.
• PSEUDOPARALELISMO:
A partir de un único computador o procesador es posible ejecutar tareas
simultáneamente. En cada instante de tiempo sólo se realiza una tarea (en
períodos muy pequeños), pero cuando transcurre un cierto tiempo puede
haberse ejecutado parte de diversos programas dando la sensación de
paralelismo.
2. Procesos.
2.1. Definición y Propiedades.
Se puede definir como un programa que ha sido almacenado en la
memoria del computador y cuya existencia es conocida por el Sistema
Operativo.
¿Cómo se crea un proceso? Cuando el sistema operativo ejecuta un
programa, éste realiza una copia del código ejecutable y la almacena en la
memoria del computador (a partir de ese instante el programa pasa a ser un
proceso). Además del código ejecutable, el proceso consta de otra información
adicional:
- Pila de proceso que contiene datos temporales.
- Sección de datos con variables globales.
- Datos sobre planificación de los procesos.
1
Tema II Procesos y Threads
21. Sistemas Informáticos en Tiempo Real Tema II
Para que un proceso pueda ser gestionado de forma adecuada, éste
debe disponer de la anterior información adicional además del código
ejecutable.
Una diferencia entre programa y un proceso es que son una entidad
pasiva y una activa, respectivamente. Es decir, mientras que un proceso
experimenta cambios de estado, un programa es una entidad pasiva de cara al
sistema operativo.
2.2. Estados de un Proceso.
En cada instante, un proceso tiene asociado un estado que determinará
la actividad de dicho proceso dentro del sistema operativo. Existen tres
distintos:
• PREPARADO: El proceso está esperando que se le asigne un
procesador para poder ejecutarse.
• EN EJECUCIÓN: El proceso es “dueño” de un procesador y sus
instrucciones se están ejecutando.
• SUSPENDIDO: El proceso está esperando que suceda algún evento
como, por ejemplo, una operación de E/S.
Admitido
ACTIVO
TERMINADO
Elegido Por el
Planificador
NUEVO
PREPARADO EN
EJECUCIÓN
expulsión
Esperar evento
Fin del evento o E/S
o de E/S
SUSPENDIDO
Figura 2.1. Transiciones entre estados de un proceso
Con respecto al estado de suspendido podemos decir que, a veces, un
proceso debe quedar suspendido para no degradar el rendimiento del sistema,
es decir, si el proceso necesita la aparición de un evento para continuar
ejecutándose, éste pasa a estado suspendido y así permitir que el procesador
quede libre hasta que ocurra dicho evento (entonces, el proceso pasa a estado
preparado).
2
Tema II Procesos y Threads
22. Sistemas Informáticos en Tiempo Real Tema II
Veamos un ejemplo de vida de un proceso. Cuando llega un nuevo
proceso, éste pasa a estado preparado de forma inmediata. En ese instante
pueden suceder dos cosas:
a) Si no existe ningún procesador libre, el proceso permanece en estado
preparado.
b) Si existe un procesador libre, el proceso pasa a ejecución.
Una vez el proceso se está ejecutando y es “dueño” del procesador,
pueden suceder dos cosas:
a) Si no existen procesos en estado preparado, éste permanece en
ejecución.
b) Si existe otro proceso, el sistema operativo puede decidir conmutar
sus estados, es decir, el que está en ejecución deja libre el
procesador pasando a estado preparado y el que está en preparado
se hace dueño del computador y ejecuta su código.
El planificador de procesos es un constituyente del sistema operativo
encargado de realizar la planificación (es decir, es el planificador el que decide
cual debe ser el estado de un proceso en todo momento). Es una tarea de las
más críticas puesto que determina el rendimiento, en gran medida, del sistema.
2.3. Información Adicional Sobre Procesos.
La tabla de procesos es donde se almacena la información adicional de
cada proceso que va a ser gestionada por el sistema operativo. El registro de
cada proceso contiene información adicional sobre él mismo como:
• Contador de programa: Indicará la dirección de la siguiente
instrucción que el proceso ejecutará.
• Estado del proceso: preparado, en ejecución o suspendido.
• Registros de la CPU: los acumuladores, apuntadores a pila y registros
de propósito general. Esta información está junto al C.P. por si se
produce un error para permitir que el proceso continúe.
• Información de planificación: Aquí se incluye la prioridad del proceso
y otros parámetros de planificación.
• Información contable: tiempo utilizado, límites de tiempo, número de
proceso...
• Información de estado de E/S: Almacena las solicitudes, los
dispositivos asignados, lista de archivos abiertos...
3
Tema II Procesos y Threads
23. Sistemas Informáticos en Tiempo Real Tema II
0 1 2 n-3 n-2 n-1
PCB PCB PCB ……… PCB PCB PCB
PLANIFICADOR
Figura 2.2. Representación de una tabla de procesos
En resumen, en la tabla de procesos se guardará toda la información
necesaria para poder reanudar la ejecución de un proceso (como si nunca
hubiera parado) después de cambiar de estado, conocido, como cambio de
contexto. El encargado de acceder a cada uno de estos registros llamados
Process Control Block (PCB) es el planificador.
2.4. Creación y Terminación de Procesos.
Puesto que el sistema operativo ha de ser potente hemos de ejecutar
procesos de forma concurrente y por ello necesitamos crear un método de
creación y terminación dinámica de procesos.
i) Creación de Procesos.
Durante la ejecución de un proceso (denominado proceso padre) éste
puede crear varios procesos nuevos (denominados procesos hijo) con una
llamada al sistema. Esta llamada al sistema se puede realizar usando funciones
de C para así solicitar la creación de nuevos procesos.
Una vez creado un proceso hijo, el padre podrá continuar su ejecución
de dos formas distintas:
• Continuar ejecutándose concurrentemente con sus hijos.
• Esperar a que los procesos hijos terminen.
Un subproceso puede obtener sus recursos directamente del sistema o
puede estar restringido a los recursos del proceso padre, que debe compartir
algunos con sus hijos o dividirlos entre sus hijos. Restringiendo a los hijos, el
proceso padre evita la saturación del sistema por la creación de demasiados
subprocesos. En el momento de creación el proceso padre puede transferir
datos iniciales a su hijo.
Ejemplo de creación de procesos.
En UNIX, un proceso nuevo se crea utilizando la llamada fork()
duplicando el proceso padre en memoria. La diferencia entre padre e hijo es
que el código de retorno del hijo es cero, mientras que el del padre es el
identificador de proceso del hijo. Posteriormente, mediante una llamada al
sistema se pone a ejecutar el proceso hijo. En UNIX, el proceso padre por
excelencia es INIT ya que todos los hijos salen de él. A estos procesos hijos se
conocen como SHELL. Esta filosofía de UNIX permite la creación de procesos
hijos de forma dinámica.
4
Tema II Procesos y Threads
24. Sistemas Informáticos en Tiempo Real Tema II
Supongamos un caso de ejemplo en el cual el proceso padre tiene que
atender peticiones de servir una web. Para atenderla el proceso padre crea un
nuevo proceso que la atenderá y después se eliminará.
INIT
SHELL SHELL SHELL SHELL
Petición web Petición web Petición web Petición web
SHELL
Petición web
Figura 2.3. Política de creación de procesos en UNIX
ii) Terminación de Procesos.
La terminación se da cuando concluye la ejecución de su última línea y el
propio proceso solicita eliminarse. No obstante existen otras circunstancias en
las cuales se puede dar la terminación como, por ejemplo, a través de una
llamada al sistema (como la llamada Kill()), un proceso puede provocar la
terminación del otro. Por lo general, el proceso padre es el único que puede
terminarlos y cuando esto ocurre puede almacenar datos provenientes del
proceso hijo que ha terminado.
Ejemplo de terminación de procesos.
Cuando un padre elimina a su hijo se hace mediante la llamada exit()
que devuelve el identificador de proceso del hijo, de forma que el padre puede
distinguir cual de sus hijos a terminado.
3. Threads.
Lo que se va a estudiar ahora es el mecanismo que permite refinar
mucho más el concepto de concurrencia y paralelismo. Nosotros podemos
subdividir un proceso (que es como una “tarea gorda”) en las tareas que lo
componen pudiendo simplificarlo en hilos de ejecución. Los hilos de ejecución
son las instrucciones que se ejecutan ininterrumpidamente. Los threads son
estas instrucciones que se ejecutan secuencialmente y que componen el
proceso.
5
Tema II Procesos y Threads
25. Sistemas Informáticos en Tiempo Real Tema II
Desde el punto de vista del programa, la secuencia de instrucciones de
un hilo de ejecución es un flujo ininterrumpido. En cambio, desde el punto de
vista del sistema operativo, los hilos de ejecución no los detecta. Es como si
fueran en el “paquete” junto con los procesos y no hubiera que “darlos de alta”.
Por lo tanto, el sistema operativo no tiene nada que ver con los threads ni con
su planificación.
P1 P1
Hilos de ejecución
Figura 2.4. Hilos de ejecución en el interior de dos procesos P1 y P2
Digamos que los threads son como una evolución del concepto del
proceso puesto que, al no necesitar ningún sistema de comunicación entre
ellos, el intercambio de información es trivial y rápido. Además, estos no son
controlados por el sistema operativo dándoles una mayor libertad de ejecución.
De esto podemos decir que la utilización de threads proporciona una
estructura fiable de programación, aumenta la productividad y el tiempo de
respuesta.
Características básicas.
- Comparten tanto el código como los datos.
- Se evita el cambio de contexto, en gran medida.
- El sistema operativo no es consciente de su existencia.
Emplear threads tiene mucha importancia puesto que se consigue una
mejora del rendimiento del sistema al minimizar el tiempo perdido durante el
cambio de contexto:
Texto Cuando se conmuta, por ejemplo,
entre el estado de preparado y el de
T T
ejecución hemos de almacenar toda la
información relacionada con la ejecución del
Hilos
proceso en el PCB. Esto provoca que el
computador emplee un tiempo que va a ser
inútil. Con los threads el tiempo que tarda en
realizarse un cambio de contexto es mínimo.
Cuanto más grande es el periodo de tiempo
Datos de cambio de contexto mayor será la
degradación de la efectividad del sistema.
Figura 2.5. Ejecución de una tarea
6
Tema II Procesos y Threads
26. Sistemas Informáticos en Tiempo Real Tema II
3.1. Ventajas de Trabajar con Threads.
Obviando la complejidad de programación de los threads, éstos aportan
muchas más ventajas que los procesos. Estas son las siguientes:
• Aumento del rendimiento del paralelismo.
Si ejecutamos diferentes threads sobre procesadores diferentes
conseguiremos aumentar el rendimiento del sistema, eso si aprovechamos el
paralelismo del hardware.
• Aumento de productividad.
Puesto que utilizando los threads conseguiremos disminuir el tiempo
inútil de cambio de contexto, lo que obtenemos es que nuestro sistema sea
más efectivo y trabaje más.
• Disminución del tiempo de respuesta.
Ya que los threads comparten información y datos, el tiempo de cambio
de contexto es más pequeño pudiendo así terminar las tareas antes y dar una
respuesta más rápida.
• Uso más eficiente de los recursos del sistema.
Al utilizar threads en vez de procesos no nos hace falta la estructura de
datos completa que le hace falta al sistema para gestionar los procesos, sino
que con menos información los threads pueden ser gestionados aprovechando
más los recursos del sistema. Es más rentable y rápido de crear.
3.2. Inconvenientes de Trabajar con Threads.
• Mayor complejidad de programación.
• No todos los programas se pueden implementar con threads.
• La conversión de antiguos programas a su equivalente con threads no
es una tarea fácil.
3.3. Modelos de Control de Threads.
Existen tres modelos tradicionales de control de threads:
i) Threads a Nivel de Usuario.
Puesto que el sistema operativo donde se ejecutan no es capaz de
gestionarlos (es decir, el sistema operativo no tiene ninguna herramienta que
los soporte), los programas que trabajan con éstos, generalmente se enlazan
con unas bibliotecas (que traen definidas e implementadas funciones) que
contienen todos los elementos necesarios para dicha gestión.
7
Tema II Procesos y Threads
27. Sistemas Informáticos en Tiempo Real Tema II
Este método tiene dos características importantes:
• Los threads permanecen invisibles para el núcleo.
• Los threads compiten entre sí para adueñarse de los recursos
asignados el proceso al cual pertenecen.
Aunque este tipo de threads tienen poco gasto, se puede observar que
tienen ciertas desventajas:
• Si un thread queda en estado suspendido bloqueará el proceso a no
ser que exista otro thread especial que encargue de recuperar el
control mediante una determinada llamada al sistema.
• No se puede aprovechar el paralelismo de un multiprocesador puesto
que si un procesador se la asigna a un proceso, los threads que lo
componen no pueden ejecutarse en otro procesador.
Un programa, Un programa,
muchos hilos muchos hilos
Soporte en Soporte en
ejecución del ejecución del
lenguaje lenguaje
Núcleo del Sistema Operativo
= Espacio de direcciones = Construcción = Proceso
lingüística o hilo a
nivel de usuario
Figura 2.6. Modelo del Thread a Nivel de Usuario
ii) Threads a Nivel de Núcleo.
En este caso, son totalmente visibles por el núcleo y, además, son
entidades planificadoras, es decir, el sistema operativo proporciona un conjunto
de llamadas al sistema para manejarlos. Ahora los denominaremos procesos
ligeros y éstos pueden competir por los recursos del sistema y para que no
quede limitado al aprovechamiento del paralelismo. Como desventaja, el
manejo de estos threads puede ser costoso al igual que el de procesos pesados
aunque en operaciones de cambio de contexto y compartición de datos sean
diez veces más rápidos.
8
Tema II Procesos y Threads
28. Sistemas Informáticos en Tiempo Real Tema II
Un programa, Un programa,
muchos hilos muchos hilos
Soporte en Soporte en
ejecución del ejecución del
lenguaje lenguaje
Núcleo del Sistema Operativo
= Espacio de direcciones = Construcción = Proceso
lingüística o hilo a
nivel de usuario
Figura 2.7. Modelo de Thread a Nivel de Núcleo
iii) Threads a Nivel Híbrido.
Este tipo de control ofrece ventajas de los de a nivel de usuario y los de
a nivel de núcleo. El usuario escribe el programa en términos de hilos a nivel de
usuario y después especifica cuantos threads son visibles para el núcleo y
pueden, por tanto competir por los recursos del sistema sin verse limitados por
los recursos del proceso al cual pertenecen.
Los threads a nivel de usuario se llaman threads y los threads a nivel de
núcleo se llaman procesos ligeros. Este es el sistema óptimo para un Sistema
Informático de Tiempo Real ya que presenta los caracteres favorables de cada
tipo.
Un programa, muchos hilos
u1 u2
Soporte en ejecución del
lenguaje
Núcleo del Sistema Operativo
= Espacio de direcciones = Construcción = Proceso
lingüística o hilo a
nivel de usuario
Figura 2.8. Modelo de Thread Híbrido
9
Tema II Procesos y Threads
29. 1. Introducción 1
1.1. ¿Qué es POSIX? 1
1.2. Programación de Sistemas concurrentes 1
2. Llamadas al Sistema 2
3. Llamadas al Sistema para Gestión de Procesos 4
3.1. Llamada al Sistema fork() 4
3.2. Llamadas al Sistema getpid() y getpid() 6
3.3. Llamadas al Sistema wait() y waitpid() 7
3.4. Llamadas al Sistema exec() 7
3.5. Llamada al Sistema exit() 8
30. Resumen del tema III – Funciones POSIX 1
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open (const char path, int oflag,…);
Etiqueta Descripción
S_IRUSR bit de permiso de lectura para el propietario
S_IWUSR bit de permiso de escritura para el propietario
Etiqueta Descripción S_IXUSR bit de permiso de ejecución para el propietario
O_RDONLY Abre el fichero en modo sólo escritura S_IRWXU lectura, escritura y ejecución para el propietario
O_WRONLY Abre el fichero en modo sólo escritura S_IRGRP bit de permiso de lectura para el grupo
O_RDWR Abre el fichero en modo lectura / escritura S_IWGRP bit de permiso de escritura para el grupo
S_IXGRP bit de permiso de ejecución para el grupo
O_APPEND Abre el fichero en modo “añadir al final”
S_IRWXG lectura, escritura y ejecución para el grupo
O_CREAT Crea el fichero si no existe
S_IROTH bit de permiso de lectura para otros
O_TTRUNC Abre el fichero existente y lo trunca a 0 S_IWOTH bit de permiso de lectura para otros
S_IXOTH bit de permiso de lectura para otros
S_IRWXO lectura, escritura y ejecución para otros
S_ISUID fija el ID del usuario al momento de la ejecución
S_ISGID fija el ID del grupo al momento de la ejecución
#include <sys/types.h>
#include <unistd.h>
ssize_t write (int fildes, const void buf, size_t nbytes);
ssize_t read (int fildes, const void buf, size_t nbytes);
#include <sys/types.h>
#include <unistd.h>
pid_t fork (void);
#include <sys/types.h>
#include <unistd.h>
uid_t getpid (void);
uid_t getppid (void);
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait (int *stat_loc);
pid_t waitpid (pid_t pid, int *stat_loc, int options);
#include <unistd.h>
int execl (const char *path, const char *arg0, ..., const char *argn,
char /*NULL*/);
int execle (const char *path, const char *arg0, ..., const char *argn,
char /*NULL*/, char *const envp[]);
int execlp (const char *file, const char *arg0, ...,const char *argn,
char /*NULL*/);
#include <uninst.h>
int execv (const char *path, char const *argv[]);
int execve (const char *path, char const *argv[], char *const envp[]);
int execvp (const char *file, char const *argv[]);
#include <stdlib.h>
void exit (int status);
Resumen del tema III – Funciones POSIX 1
31. Sistemas Informáticos en Tiempo Real Tema III
1. Introducción.
1.1. ¿Qué es POSIX?
En este tema estudiaremos las herramientas necesarias para programar
sistemas concurrentes ya que todos los sistemas Informáticos de Tiempo Real
cumplen esta propiedad.
Debido a la necesidad de estandarizar los distintos sistemas UNIX (la
diferencia de programación y la falta de portabilidad del código provoca estas
diferencias a nivel de sistema entre los distintos sistemas operativos UNIX) la
IEEE ha desarrollado un grupo de estándares: POSIX (Potable Operating
System Interface). Este especifica la interfaz entre el sistema operativo y el
usuario de modo que los usuarios podemos interactuar con el sistema
operativo. Gracias a esta estandarización se permite que los programas de las
diversas aplicaciones sean transportables entre distintas plataformas.
Estándar Descripción
POSIX.1 Interfaz del sistema para programas de aplicación (API) en lenguaje C
POSIX.1b Rectificación 1 del API: Extensión de tiempo real en C
POSIX.1c Rectificación 2 del API: Extensión de hilos de control
POSIX.2 Intérprete de comandos y útiles
POSIX.4 Ahora llamado POSIX.1c
POSIX.5 POSIX.1 lenguaje ADA
POSIX.6 Seguridad
POSIX.7 Administración del sistema
Tabla 3.1. Algunos estándares POSIX
1.2. Programación de Sistemas Concurrentes.
Con respecto a la programación concurrente en UNIX podemos decir que
se realiza de dos maneras:
• Mediante la implementación de programas en un lenguaje diseñado para
dar soporte a la concurrencia como Java o Ada. La concurrencia la
proporciona el lenguaje.
• Mediante la utilización del lenguaje (estándar bajo un sistema UNIX que
cumpla el estándar POSIX). La concurrencia, en este caso, la proporciona
el sistema operativo. En UNIX, los procesos solicitan servicios al sistema
utilizando llamadas al sistema (éstas son puntos de entrada directa al
núcleo). El núcleo es una colección de programas muy eficaces que
gobiernan el control del sistema operativo.
Aparte de las llamadas (que son parte intrínseca del núcleo) están
disponibles muchas funciones de la biblioteca que pueden o no hacer uso de
llamadas al sistema.
1
Tema III Funciones POSIX 1
32. Sistemas Informáticos en Tiempo Real Tema III
Programas de usuario (procesos)
2. Llamadas al Sistema.
Son un conjunto de servicios Interfaz de llamadas al sistema
básicos, proporcionados por el sistema
operativo, que definen una vía de
Kernel
comunicación entre un proceso y el
sistema operativo. Con interrupciones se
consigue la implementación de las Hardware (Recursos)
llamadas al sistema que en UNIX se
clasifican en 5 categorías: Figura 3.1. Llamadas al sistema
1. Llamadas al sistema para gestión de procesos.
2. Llamadas al sistema para gestión de señales.
3. Llamadas al sistema para gestión de memoria.
4. Llamadas al sistema para gestión de ficheros y directorios.
5. Llamadas al sistema para gestión de Entrada/Salida.
Veamos a continuación un ejemplo sencillo de la creación de un fichero
(si este no existe) y en el cual se escribe la cadena “Esto es un ejemplo”:
Usando la llamada open() podemos abrir o crear un nuevo fichero. La
sintaxis es:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open (const char path, int oflag,…);
donde el primer argumento es el nombre del fichero que se quiere abrir
y el segundo indica el modo en que se va a abrir el fichero (estos modos se
representan mediante etiquetas predefinidas en el fichero cabecera fcntl.h).
Cabe decir que podemos utilizar el operador lógico OR para obtener un efecto
combinado.
Etiqueta Descripción En el caso de que se vaya a
O_RDONLY Abre el fichero en modo sólo escritura crear un fichero, los puntos
O_WRONLY Abre el fichero en modo sólo escritura
O_RDWR Abre el fichero en modo lectura / escritura suspensivos se sustituyen por un
O_APPEND Abre el fichero en modo “añadir al final” tercer parámetro de tipo mode_t
O_CREAT Crea el fichero si no existe que especifica los permisos del
O_TTRUNC Abre el fichero existente y lo trunca a 0
fichero que se va a crear.
Tabla 3.2. Modos de apertura de un fichero
Usuario Grupo Otros
r w x r w x r w x
Bit 8 Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
Figura 3.2. Patrón de la máscara de permisos
2
Tema III Funciones POSIX 1
33. Sistemas Informáticos en Tiempo Real Tema III
Etiqueta Descripción Los archivos pueden ser
S_IRUSR bit de permiso de lectura para el propietario
S_IWUSR bit de permiso de escritura para el propietario empleados por: un usuario, un grupo o
S_IXUSR
S_IRWXU
bit de permiso de ejecución para el propietario
lectura, escritura y ejecución para el propietario
el resto. Los permisos de cada una de
S_IRGRP bit de permiso de lectura para el grupo estas clases son: leer (r), escribir (w) y
S_IWGRP bit de permiso de escritura para el grupo
S_IXGRP bit de permiso de ejecución para el grupo
ejecutar (x). Cada fichero tiene
S_IRWXG lectura, escritura y ejecución para el grupo asociados 9 bits donde cada BIT a 0 o
S_IROTH bit de permiso de lectura para otros
S_IWOTH bit de permiso de lectura para otros a 1 quita o da el permiso
S_IXOTH
S_IRWXO
bit de permiso de lectura para otros
lectura, escritura y ejecución para otros
correspondiente.
S_ISUID fija el ID del usuario al momento de la ejecución
S_ISGID fija el ID del grupo al momento de la ejecución
Con respecto a dos operaciones
Tabla 3.3. Etiquetas de permisos de un fichero básicas con ficheros: leer y escribir,
podemos decir que se utilizan a través
de las llamadas al sistema read() y write(). La llamada read() y write() tiene la
siguiente definición:
#include <sys/types.h>
#include <unistd.h>
ssize_t write (int fildes, const void buf, size_t nbytes);
ssize_t read (int fildes, const void buf, size_t nbytes);
Esta llamada intenta escribir (respectivamente leer) nbytes bytes
tomados del buffer buf en el archivo cuyo descriptor es fildes. Si esta llamada
tiene éxito entonces devuelve el número de bytes escritos. El ejemplo sería el
siguiente:
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#define BLKSIZE 100
void main (void)
{
int fd, bytes_escritos, bytes_leidos; /*descriptor de fichero*/
char buffer[BLKSIZE];
mode_t modo = S_IRWXU; /* modo de r, w y x para el propietario*/
strcpy(buffer, "Esto es un ejemplon");
if ((fd = open ("ejemplo", O_RDWR | O_CREAT, modo))== -1)
/*abre el fichero ejemplo en modo lectura/escritura o lo
crea si no existe */
perror ("Error al abrir o crear el fichero");
/*muestra un error si no puede abrir/crear el fichero*/
else
{
bytes_escritos = write(fd, buffer, strlen(buffer));
/* escribe buffer de tamaño sizeof(buffer) en fd */
bytes_leidos = read(fd, buffer, BLKSIZE);
buffer[bytes_leidos]='0';
printf("%s son %d n", buffer, bytes_leidos);
}
exit(0);
}
3
Tema III Funciones POSIX 1
34. Sistemas Informáticos en Tiempo Real Tema III
3. Llamadas al Sistema para Gestión de Procesos.
3.1. Llamada al Sistema fork().
La función fork() permite la creación de un nuevo proceso, que es una
copia exacta (un doble con un nuevo identificador pero con el mismo código).
Una vez creado el hijo, éste comienza su ejecución en la línea siguiente a la
última llamada a la función fork(), es decir, a partir de cuando fue creado. La
sintaxis es:
#include <sys/types.h>
#include <unistd.h>
pid_t fork (void);
Se puede observar que no tiene ningún parámetro y devuelve un entero.
fork() devuelve el identificador de procesos del nuevo proceso creado al
proceso padre y devuelve un cero al hijo. Si en un programa escribo la función
fork(), no tengo que pasarle ningún parámetro, pues se supone que el proceso
hijo creado es del proceso o programa que estamos escribiendo. El proceso hijo
se empieza a ejecutar a partir de la línea donde se a realizado la llamada fork().
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
void main (void)
{
int pid;
pid = fork();
switch (pid)
{
case -1: perror ("No se ha podido crear el hijo");
break;
case 0: printf("Soy el hijo, mi PID es %d y mi PPID es
%dn", getpid(), getppid());
break;
default: printf ("Soy el padre, mi PID es %d y el PID de
mi hijo es %dn", getpid(), pid);
}
exit(0);
}
El ejemplo se puede expresar gráficamente como:
PADRE
………………………
……………………… Comienza su ejecución
……………………… después del fork ()
fork ()
……………………… HIJO ………………………
……………………… ……………………… Este fragmento de
……………………… ……………………… código no es ejecutado
fork ()
………………………
……………………… Este fragmento de
……………………… código si es ejecutado
Figura 3.3. Uso de la función fork () 4
Tema III Funciones POSIX 1
35. Sistemas Informáticos en Tiempo Real Tema III
El proceso hijo hereda del padre lo siguiente:
- Con qué permisos se crean los ficheros.
- Variables de entorno y argumentos, es decir, las condiciones en que
se va a ejecutar el proceso.
- Descriptores de fichero.
El proceso hijo difiere del padre en lo siguiente:
- El proceso hijo tiene su propio identificador PID.
- El hijo tiene el identificador del padre PPID, de forma que sabemos
cual es su padre (Parent Process Identificator).
- Como los sistemas operativos UNIX tienen un contador que mide
cuánto tiempo lleva un proceso ejecutándose, se inicializa la
información de contabilidad del proceso hijo.
Los errores que pueden darse al ejecutar la llamada fork() son:
- Saturación del sistema por sobrepasar el límite de procesos
permitidos.
- Excedente de procesos máximos para un usuario.
- Insuficiencia en la memoria.
Si la función fork() devuelve un –1 esto significa que no se ha podido
crear un hijo. Con respecto a la ejecución del fork() en un proceso, es necesario
realizar una aclaración. Al ejecutarla, se crea un hijo cuyo código es igual pero
con el contador de programa señalando a la línea siguiente al fork() que lo ha
creado.
Cuando se ejecuta la línea de código 5 (por ejemplo), donde está el
fork(), se crea un hijo del proceso padre.
En este momento, tenemos dos hilos de ejecución, es decir, de un
programa ejecutándose, se pasa a leer dos (el mismo que ya estaba
ejecutándose y un programa hijo, que se ejecuta a partir de la línea que lo
creó). Por tanto, el proceso P2 comienza a ejecutarse en la línea posterior al
fork() que lo ha creado. Ahora tengo dos programas que se están ejecutando
en un determinado orden, que ya veremos (primero P1 y luego P2, a la vez,
primero P2 y luego P1,...). Supongamos que van ejecutándose a la vez.
5
Tema III Funciones POSIX 1
36. Sistemas Informáticos en Tiempo Real Tema III
P1
#include <stdio.h> Las llaves indican el
código ejecutado por
int main (void) cada proceso
{
…………………………………………………
…………………………………………………
SE CREA UN HIJO DE P1
pid1 = fork ( );
P2
pid2 = fork ( );
#include <stdio.h>
…………………………………………………
…………………………………………………
SE CREA OTRO
int main (void)
HIJO DE P1
} {
…………………………………………………
…………………………………………………
pid1 = fork ( );
SE CREA UN
HIJO DE P2
P3 pid2 = fork ( );
…………………………………………………
#include <stdio.h>
…………………………………………………
}
int main (void)
{
………………………………………………… P4
…………………………………………………
#include <stdio.h>
pid1 = fork ( );
int main (void)
{
pid2 = fork ( ); …………………………………………………
…………………………………………………
…………………………………………………
………………………………………………… pid1 = fork ( );
}
pid2 = fork ( );
…………………………………………………
…………………………………………………
Figura 3.4. Creación de procesos hijo }
El proceso P1 tiene en la siguiente línea de código otro fork(), por lo que
vuelve a crear otro hijo suyo, que se ejecutará a partir de la línea siguiente. Al
mismo tiempo, el proceso P2 tiene en la línea que empieza a ejecutar un fork(),
por lo que crea un hijo suyo que se empezará a ejecutar a partir de ese fork()
que lo ha creado.
En total, se han creado 3 hijos, y de 1 programa en ejecución o proceso
que teníamos al principio, tenemos ahora 4 procesos ejecutándose en el orden
en que determine el planificador.
3.2. Llamadas al Sistema getpid() y getppid().
Ambas se definen de la siguiente forma:
#include <sys/types.h>
#include <unistd.h>
uid_t getpid (void);
uid_t getppid (void);
Con estas llamadas obtenemos las PID’s del proceso que la invoca y de
su proceso padre respectivamente. El tipo uid_t es un entero predefinido en
<sys/types.h>.
6
Tema III Funciones POSIX 1
37. Sistemas Informáticos en Tiempo Real Tema III
3.3. Llamada al Sistema wait() y waitpid().
Si un padre desea esperar hasta que el proceso hijo termine de
ejecutarse, éste debe realizar la llamada al sistema wait o waitpid que se
definen como sigue:
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait (int *stat_loc);
pid_t waitpid (pid_t pid, int *stat_loc, int options);
La llamada wait() suspende la ejecución del proceso que lo invoca hasta
que finaliza alguno de sus hijos. Si el padre ejecuta esta llamada, se le notifica
la terminación y el código de terminación del proceso hijo.
Si el padre no está ejecutando wait() y termina, entonces no espera a
que su proceso hijo termine. Por tanto, la conexión entre el proceso hijo y su
padre desaparece y el proceso hijo sigue ejecutándose sin que se entere el
padre.
3.4. Llamada al Sistema exec().
La familia de llamadas exec() cambia la imagen de memoria de un
proceso por el contenido de un fichero ejecutable. La forma habitual de utilizar
la combinación fork/exec es dejar que el hijo ejecute exec() mientras el padre
continua la ejecución normal. Existen 6 variaciones de exec() que se distinguen
por la forma en que son pasados los argumentos de la línea de comandos y el
entorno que utilizan. Las seis variaciones se pueden agrupar en dos grupos:
• Llamadas execl: execl(), execlp(), execle().
Las llamadas execl (execl(), execlp(), execle()) pasan los argumentos de
la línea de comandos del programa mediante una lista. Son útiles si se conoce
el número de argumentos que se van a pasar
#include <unistd.h>
int execl (const char *path, const char *arg0, ..., const char *argn,
char /*NULL*/);
int execle (const char *path, const char *arg0, ..., const char *argn,
char /*NULL*/, char *const envp[]);
int execlp (const char *file, const char *arg0, ...,const char *argn,
char /*NULL*/);
execle() permite pasar nuevos valores de variables de entorno.
execlp() permite tomar el path por defecto del entorno.
7
Tema III Funciones POSIX 1
38. Sistemas Informáticos en Tiempo Real Tema III
• Llamadas execv: execv(), execvp(), execve().
Pasan los argumentos de la linea de comando en un array de argumentos.
#include <uninst.h>
int execv (const char *path, char const *argv[]);
int execve (const char *path, char const *argv[], char *const
envp[]);
int execvp (const char *file, char const *argv[]);
execve() permite pasar nuevos valores de variables de entorno.
execvp() permite tomar el path por defecto del entorno.
3.5. Llamada al Sistema exit().
Fuerza la terminación de un proceso devolviendo un código de error.
Está implícita en la terminación de todos los procesos. Al finalizar un proceso se
recuperan todos los recursos asignados al proceso.
Si el padre del proceso que termina está ejecutando wait() se le notifica
la terminación y el código de terminación sólo cuando termine de realizar dicha
espera. Si el padre no ejecuta wait() el proceso se transforma en un proceso
zombie huérfano hasta que es adoptado por INIT. La sintaxis sería la siguiente:
#include <stdlib.h>
void exit (int status);
El campo status se emplea para imprimir un mensaje de error por
pantalla si ha ocurrido un error, ya que el valor de status indicará el mensaje
que saldrá por pantalla.
8
Tema III Funciones POSIX 1