Вы находитесь на странице: 1из 91

FUNDAMENTOS DEL SISTEMA

OPERATIVO UNIX
Laura Diges

UNED
Ingeniería Informática
TEMA 1: DISEÑO DEL SISTEMA
OPERATIVO UNIX
https://linuxconfig.org/bash-scripting-tutorial

INTRODUCCIÓN

 Programa: fichero ejecutable.


 Proceso: instancia de un programa en ejecución.
 Sistema operativo UNIX: programa – núcleo – que controla el hardware, administra procesos y
suministra servicios para ellos. Incluye otros programas y utilidades. Filosofía de simplicidad y
consistencia. Reside permanentemente en memoria principal.

PRINCIPALES CARACTERÍSTICAS:

 Escrito en C. Fácil de entender, modificar y portar.


 Interfaz de usuario sencilla y potente.
 Suministra primitivas: escribir programas complejos a partir de otros más sencillos.
 Jerarquía de ficheros.
 Formato consistente de archivos.
 Interfaz simple y consistente para periféricos.
 Multiusuario y multiproceso.
 Oculta la arquitectura de la máquina al usuario.

DISTRIBUCIONES:

 System V – SRV4
 BSD (MacOS – BSD y XNU basado en Mach)
 OSF/1
 SunOS y Solaris (basado en SVR4)

ESTÁNDARES INTERFAZ:

 SVID – System V Interface Definition


 POSIX – Portable Operating System based on UNIX
 Guía de portabilidad X/Open – Fabricantes de computadores

PROYECTO GNU: CREAR UN SO SIMILAR Y COMPATIBLE CON UNIX BASADO EN POSIX.

 Linux – basado en Minix. Desarrollo continuo en dos fases: desarrollo y estabilización.


 Licencia open source: GNU GPL

ARQUITECTURA DEL SISTEMA OPERATIVO UNIX

Cuatro niveles o capas:

1. Hardware
2. Núcleo del sistema – kernel en C y ensamblador
1
3. Programas estándar y ejecutables del usuario – llamadas al sistema
4. Programas de usuario – usan programas del nivel 3 para comunicarse con el núcleo. Ej.:
compilador C cc usa cpp, comp, as y ld.

SERVICIOS REALIZADOS POR EL NÚCLEO

 Control de la ejecución de los procesos.


 Planificación de los procesos para su ejecución en la CPU.
 Asignación de la memoria principal.
o Utilización de dispositivo de intercambio:
 política de intercambio o
 política de demanda de páginas.
 Protección del espacio de direcciones de un proceso en ejecución. Memoria compartida.
 Asignación de memoria secundaria para almacenamiento y recuperación eficiente de los datos
de usuario.
o Asigna memoria secundaria para los ficheros de usuario.
o Reclama el espacio no utilizado.
o Estructura el sistema de ficheros de forma entendible.
o Protege los ficheros de usuario de accesos ilegales.
 Regulación del acceso de los procesos a los dispositivos periféricos (terminales, disco, red,
etc.).
 Administración de archivos y dispositivos.
 Tratamiento de interrupciones y excepciones.

MODOS DE EJECUCIÓN

MODO USUARIO Y MODO NÚCLEO

La ejecución de procesos está dividida en dos modos para proteger el espacio de direcciones de
memoria asociado al núcleo y a cada proceso.

MODO USUARIO:
 Acceso a código, datos y pila de su espacio de direcciones.
 No tiene acceso a espacios de otros procesos o del núcleo.
 No puede acceder a todo su espacio de direcciones.

MODO NÚCLEO O SUPERV ISOR:


 Acceso completo a su propio espacio de direcciones y al del núcleo.
 No puede acceder a espacio de otros procesos.
 Se ejecuta el núcleo en nombre del proceso que lo invoca.

PASO DE MODO USUARIO A MODO NÚCLEO:


 Llamadas al sistema.
 Interrupciones hardware o software.
 Excepciones.

TIPOS DE PROCESOS

Jerarquía de procesos.
2
Herencia de usuario y grupo del padre.

TRES TIPOS:
 Procesos de usuario:
o Asociados a un usuario.
o Ejecución en modo usuario.
o Llamadas al sistema  pasa a modo núcleo.
 Procesos demonio:
o Sin usuario – root.
o Ejecución en modo usuario.
o Llamadas al sistema  pasa a modo núcleo.
o Tareas periódicas de administración del sistema (ej.: redes, trabajos de impresoras en
línea, etc.).
o Son hijos de init.
o No asociados a ningún terminal.
 Procesos del núcleo:
o Sin usuario – root.
o Ejecución en modo núcleo exclusivamente.
o Tareas de administración del sistema (ej. Proceso intercambiador, ladrón de páginas,
etc.).
o Mayor control que demonios en prioridades de planificación.
o Son parte del código del núcleo que reside en memoria principal.
o Acceso directo a algoritmos y datos del núcleo, no requiere llamadas al sistema.
o Los cambios en los procesos del núcleo requieren recompilar el núcleo.

INTERRUPCIONES Y EXCEPCIONES

Dispositivos que utilizan el mecanismo de interrupciones para notificar al núcleo que se ha completado
una operación, interrumpiendo a la CPU mientras se está ejecutando un proceso:

 Reloj del sistema.


 Periféricos de E/S.
 Terminales.

TIPOS DE INTERRUPCIONES:
 Interrupciones hardware – eventos asíncronos que ocurren entre dos instrucciones de un
proceso, ajenos al proceso actual.
 Interrupciones software o traps – ejecución de ciertas instrucciones especiales, síncronas.

EXCEPCIONES
Aparición de eventos síncronos inesperados, errores, causados por un proceso durante la ejecución de
una instrucción.

TRATAMIENTO DE INTER RUPCIONES Y EXCEPCIONES:


Interrupción que interrumpe a otra interrupción. Solución: prioridades.

Nivel de prioridad de interrupción, o nivel de ejecución del procesador asociado a cada tipo de
interrupción, usualmente 0 es el nivel más bajo.

3
El npi se almacena en un registro de estado del procesador.

Enmascaramiento o bloqueo de interrupciones: núcleo configura el npi a un nivel, se enmascara ese


nivel e inferiores.

NIVELES DE PRIORIDAD DE INTERRUPCIÓN TÍPICOS:


MAX
Errores de la máquina
Reloj
Discos
Dispositivos de red
Terminales
Interrupciones software
MIN

ESTRUCTURA DEL SISTEMA OPERATIVO UNIX

NIVEL USUARIO

 Programas de usuario.
 Demonios.

INTERACCIÓN CON EL N ÚCLEO MEDIANTE LLAMA DAS AL SISTEMA:


 Mediante el uso de librerías de llamadas al sistema. Enlazadas en tiempo de compilación al
fichero objeto del programa usuario.
 Forma directa en ensamblador.

NIVEL DEL NÚCLEO

Módulos más importantes del núcleo:

SUBSISTEMA DE FICHEROS
 Reserva espacio en memoria principal para las copias de los ficheros.
 Administra el espacio libre del sistema de ficheros.
 Controla el acceso a los ficheros.
 Regula el intercambio de datos, lectura y escritura, entre los ficheros y los usuarios.
 Etc.

La interfaz del sistema de ficheros especifica el comportamiento y la semántica de las llamadas al


sistema asociadas:

 open
 write
 stat
 chown
 chmod

4
Abstracciones al usuario: ficheros, directorios, descriptores de ficheros y sistemas de ficheros.

Interfaz nodo-v/sfv: soporte para distintos tipos de sistemas de ficheros UNIX o Windows.

Manejadores o drivers de dispositivos: módulos del núcleo que gestionan la comunicación con los
dispositivos.

TIPOS DE FICHEROS:
 Ordinarios: bytes de datos organizados como un array lineal.
 Directorios: ficheros que jerarquizan el sistema.
 Enlaces simbólicos: ficheros que contienen el nombre de otro fichero.
 Tuberías sin nombre y ficheros FIFO: comunicación con flujo de datos no estructurados de
tamaño fijo.
 Ficheros de dispositivos: ficheros para la comunicación con periféricos.
o Modo bloque: contiene un array de bloques de tamaño fijo. Transferencia mediante
caché de buffers de bloques, gestionado por el núcleo.
o Modo carácter: no utilizan buffers, transferencia a menor velocidad. Información no
organizada, secuencia lineal de bytes.

SUBSISTEMA DE CONTRO L DE PROCESOS

TAREAS:
 Sincronización de procesos.
 Comunicación entre procesos.
 Administración de la memoria principal.
 Planificación de procesos.

LLAMADAS AL SISTEMA PARA EL CONTROL DE PROCESOS:


 fork
 exec
 exit
 wait
 signal

MÓDULOS DEL SUBSISTEMA DE CONTROL DE PROCESOS


 Módulo de administración o gestión de memoria.
 Módulo de planificación – scheduler.
 Módulo de comunicación de procesos.

MÓDULO DE CONTROL DE L HARDWARE


Responsable del manejo de las interrupciones y de la comunicación con el hardware de la máquina.

LA INTERFAZ DE USUARIO PARA EL SISTEMA DE FICHEROS

FICHEROS Y DIRECTORIOS

Un fichero es un contenedor permanente de datos. Acceso secuencial y aleatorio. Posibilidad de acceso


mediante flujos de bytes.

5
Un directorio contiene información sobre el nombre de los ficheros y directorios que residen en él.

ARBOL DE DIRECTORIOS:
 /bin. programas ejecutables esenciales del sistema.
 /etc. Ficheros de configuración del sistema.
 /dev. Ficheros de dispositivos.
 /usr. Programas y ficheros de configuración del sistema.

RUTA DE ACCESO:
 Absoluta
 Relativa

ENLACES:
 Duro
 Simbólico

ATRIBUTOS DE UN FICH ERO


Almacenados en una estructura del disco llamada nodo índice o nodo-i. Formato dependiente del
sistema de ficheros.

 Nombre del fichero


 Tipo de fichero
 Permisos e indicadores de modo
 Numero de enlaces duros al fichero
 Tamaño del fichero en bytes
 Identificador del dispositivo: entero del sistema de ficheros
 Numero de nodo-i
 Identificadores de usuario real, uid, y del grupo real, gid, del propietario
 Información asociada al tiempo: creación, acceso, modificación

LLAMADAS AL SISTEMA PARA CONOCER Y MANIPULAR LOS ATRIBUTOS DE UN FICHERO:


 stat y fstat
 link y unlink
 utimes
 chown
 chmod

MODO DE UN FICHERO
Modelo de seguridad DAC – discretionary Access control

El sticky bit se utiliza en la actualidad en directorios para evitar que los archivos contenidos puedan ser
renombrados por otros usuarios que no sean el propietario y el administrador aún cuando tengan
permisos de escritura.

6
MÁSCARA DE MODO: 16 BITS

MÁSCARA DE MODO MANIPULABLE

12 bits – cuatro dígitos octales: M3 M2 M1 M0

CONVERSIÓN DE LA CIFRA OCTAL EN LA MÁSCARA DE MODO

Cifra octal Mj Bit 3*j+2 Bit 3*j+1 Bit 3*j


0 0 0 0
1 0 0 1
2 0 1 0
3 0 1 1
4 1 0 0
5 1 0 1
6 1 1 0
7 1 1 1

Ejemplo:

7700 – 111 111 000 000

0655 – 000 110 101 101

DESCRIPTORES DE FICH EROS


Cuando un usuario invoca open, el núcleo crea un objeto de fichero abierto en memoria principal y es
almacenado en la tabla de ficheros.

El descriptor de fichero es un entero positivo que identifica el objeto de fichero abierto local a cada
proceso.

7
Los descriptores de fichero asociados a un proceso se guardan en la tabla de descriptores de ficheros
del proceso.

Arranque de UNIX: el sistema abre tres ficheros que ocupan las tres primeras entradas de la tabla de
descriptores:

 Fichero estándar de entrada – stdin – 0


 Fichero estándar de salida – stout – 1
 Fichero estándar de salida de mensajes de error – stderr – 2

Es posible redireccionar la entrada/salida estándar.

El proceso pasa el descriptor de fichero en llamadas read o write, lo que hace más eficiente el
sistema.

Cada descriptor de fichero representa una sesión de trabajo independiente, contiene el modo de
apertura y el puntero de lectura/escritura.

Los ficheros son accedidos secuencialmente por defecto.

El puntero en el objeto de fichero abierto permite al núcleo aislar las diferentes sesiones de trabajo
sobre un mismo fichero. Múltiples procesos comparten de forma transparente el mismo fichero.

Se puede duplicar un descriptor usando dup o dup2.

Los descriptores de fichero se heredan del padre con fork.

OPERACIONES DE ENTRA DA/SALIDA SOBRE UN FICHERO

APERURA Y CIERRE DE UN FICHERO

CREAT

Crea un fichero.

fd=creat(ruta,modo);

 ruta: ruta del fichero a crear.


 modo: máscara de modo octal.

Éxito: fp = descriptor de fichero

Error: fp = -1

OPEN

Abre un fichero.

fd=open(path,flags);

 path: ruta del fichero a crear.


 flags: máscara de modo octal o máscara de bits que especifica permisos de apertura.

Éxito: fp = descriptor de fichero

Error: fp = -1

8
El argumento flags como máscara de bits: combinación de constantes con “OR” a nivel de bit (‘|’).

Constantes definidas en el fichero de cabecera <fcntl.h>:

 O_RDONLY
 O_WRONLY
 O_RDWR

Sólo una de las anteriores o el modo de apertura queda indefinido.

 O_CREAT
 O_APPEND
 O_TRUNC

Con O_CREAT, open crea un fichero antes de abrirlo si no existe:

fd=open(path,flags);

fd=open(path,flags,modo);

 modo: especifica los permisos máximos de acceso, pueden estar limitados por umask.

CLOSE

Los ficheros abiertos son cerrados automáticamente cuando un proceso termina.

Cerrar ficheros explícitamente:

resultado = close(fd);

 fd: descriptor del fichero a cerrar.

Éxito: fp = descriptor de fichero

Error: fp = -1

MÁSCARA DE MODO DE UN USUARIO UMASK


Cada usuario tiene asignada una umask dependiendo de su perfil.

 Obtener umask en terminal:

umask

 Desde C, retorna la máscara antigua tras establecer la nueva:

mode_t umask(mode_t mascara_nueva)

Los permisos de un fichero en su creación dependen del modo y del umask del usuario que lo crea.

modo_efectivo = ~umask & modo

Si un bit vale 1 en umask, el modo se convierte en 0, con umask a cero el modo se mantiene.

 Usuario normal, umask = 0002


 root, umask = 0022

9
LECTURA Y ESCRITURA EN UN FICHERO

READ

Leer un fichero.

nread=read(fd,buffer,nbytes);

 fd: descriptor de fichero.


 buffer: array de caracteres que almacena los datos que se lean. Usuario responsable de tamaño
adecuado.
 nbytes: número de bytes que se quieren leer.

Éxito: nread = número de bytes leídos

Error: nread = -1

Si se intenta leer más allá del final de fichero: nread = 0

Comienza la lectura en el puntero almacenado en el objeto de fichero. La lectura avanza el puntero.

Puede leer menos de nbytes si alcanza EOF o en FIFO o dispositivos no hay datos suficientes.

Nunca leerá más de nbytes.

WRITE

Escribe un fichero.

nwrite=write(fd,buffer,nbytes);

 fd: descriptor de fichero.


 buffer: array de caracteres que almacena los datos que se van a escribir.
 nbytes: número de bytes que se quieren escribir.

Éxito: nread = número de bytes escritos

Error: nread = -1

ACCESO ALEATORIO A UN FICHERO


UNIX permite tanto accesos secuenciales como aleatorios a un fichero, por defecto secuencial.

Puntero inicializado a cero cuando se abre un fichero.

LSEEK

Accesos aleatorios configurando el puntero de lectura/escritura.

resultado=lseek(fd,offset,origen);

 fd: descriptor de fichero.


 offset: número de bytes que se desplaza el puntero. Entero positivo, avanza; negativo,
retrocede.
 origen: posición desde donde se va a desplazar el puntero.

Valores constantes definidos en <stdio.h> para origen:

10
 SEEK_SET – avanza respecto al inicio – 0
 SEEK_CUR – avanza respecto a su posición actual – 1
 SEEK_END – avanza respecto al final – 2

Éxito: resultado = posición nueva desde el origen del fichero en bytes

Error: resultado = -1

LIBRERÍA ESTÁNDAR DE FUNCIONES DE ENTRADA/SALIDA

Forma parte de la definición del ANSI C.

La librería gestiona más eficientemente los accesos a disco manejando memorias intermedias.

Un fichero es un flujo de bytes o flujo de datos.

Información de control almacenada en una estructura de tipo FILE definida en <stdio.h>

Funciones importantes de esta librería: getchar, putchar, scanf, printf, gets, puts, fopen,
fread, fwrite, fclose, feof, fgets, fgetc, fputs, fputc, fscanf y fprintf.

Constantes importantes definidas en esta librería: SEEK_SET, SEEK_CUR, SEEK_END y EOF.

EOF = -1, retorno en algunas funciones que señala final de fichero.

FUNCIÓN FOPEN

#include <stdio.h>

FILE *fopen(const char *nombre_fichero, const char *modo);

Abre nombre_fichero, lo asocia a un flujo de datos y devuelve un puntero al mismo.

modo, cadena de caracteres:

 “r”. Abrir existente lectura.


 “w”. Abrir existente escritura.
 “a”. Abrir para escribir al final, o crea y escribe.
 “r+”. Abrir existente para lectura y escritura.
 “w+”. Abrir existente para lectura y escritura, trunca tamaño a 0 bytes. Si no existe crea.

FUNCIÓN FREAD

#include <stdio.h>

size_t fread (char *p, size_t longitud, size_t nelem, FILE *flujo);

size_t: tipo predefinido, entero sin signo, en <stdio.h>, almacena el resultado del operador
sizeof.

Lee nelem bloques de datos, de tamaño longitud, desde flujo y los copia en el array p.

Devuelve el total de bloques leídos o 0 si encuentra EOF. Error, -1?

FUNCIÓN FWRITE

11
#include <stdio.h>

size_t fwrite (const char *p, size_t longitud, size_t nelem, FILE *flujo);

Escribe en flujo nelem bloques de datos de tamaño longitud desde el array p.

Devuelve el total de bloques escritos, o un número distinto a nelem si hay error.

FUNCIÓN FCLOSE

#include <stdio.h>

int fclose (FILE *flujo);

Cierra el fichero asociado con flujo.

La memoria intermedia asociada a flujo se escribe en disco y se libera.

Éxito: 0

Error: EOF

FUNCIÓN FEOF

#include <stdio.h>

int feof (FILE *flujo);

Devuelve valor != 0 si EOF = 1, es decir, en final de fichero.

FUNCIÓN FGETS

#include <stdio.h>

char *fgets (char *p, int n, FILE *flujo);

Lee de flujo y almacena en el array p.

Para de leer cuando:

 Almacena n-1 caracteres, o


 Almacena ‘\n’

Siempre almacena un carácter nulo ‘\0’ al final del array.

Éxito: puntero al array

Error o EOF: puntero nulo, NULL

FUNCIÓN FGETC

#include <stdio.h>

int fgetc (FILE *flujo);

Lee un carácter de flujo.

Éxito: devuelve el carácter leído como entero sin signo


12
Error o EOF: EOF

FUNCIÓN FPUTS

#include <stdio.h>

int fputs (const char *p, FILE *flujo);

Escribe p en flujo.

No escribe el carácter nulo de terminación.

Éxito: devuelve valor no negativo

Error: EOF

FUNCIÓN FPUTC

#include <stdio.h>

int fputc (int c, FILE *flujo);

Escribe el carácter c en flujo.

Éxito: devuelve c

Error o EOF: EOF

FUNCIÓN FSCANF

#include <stdio.h>

int fscanf (FILE *flujo, const char *formato[, dir, …]);

Lee de uno en uno una serie de campos de entrada desde flujo, los convierte al tipo de datos y
formato indicados en formato. Almacena en las direcciones dir pasadas, una por campo.

Éxito: Nº de campos leídos, formateados y almacenados

EOF: EOF

No se almacenó nada: 0

FUNCIÓN FPRINTF

#include <stdio.h>

int fprintf (FILE *flujo, const char *formato[, argumento, …]);

Genera texto formateado.

Da el formato especificado en formato a los argumentos y escribe en flujo.

Un especificador de formato para cada argumento.

Éxito: devuelve Nº de caracteres escritos

Error: EOF
13
ORIGEN DEL TÉRMINO PROCESO DEMONIO

De los programadores del proyecto MAC del MIT: el demonio de Maxwell, trabaja continuamente sin
ser visto ordenando moléculas. De la mitología, demonios que hacían tareas tediosas que los dioses no
querían realizar.

Demonio: tipo especial de proceso que se ejecuta de forma continua en segundo plano y que no puede
ser controlado directamente por el usuario ya que no está asociado con una terminal o consola. Ej.:
administración y control de redes, ejecución de actividades dependientes del tiempo, administración de
trabajos en las impresoras en línea, etc.

No utiliza los dispositivos de entrada y salida estándar para comunicar errores o registrar su
funcionamiento, sino que usa archivos del sistema en zonas especiales o se utilizan otros demonios
especializados en dicho registro.

RESUMEN TEMA 1

1. En primer lugar, se introducen los términos proceso y núcleo. Un proceso es una instancia de un
programa en ejecución. El núcleo administra a los procesos y suministra varios servicios para ellos. El
sistema operativo UNIX de forma general incluye tanto el núcleo como otros programas y utilidades.

El núcleo es el único programa indispensable sin el cual ningún otro podría ejecutarse, y define la
interfaz de programación del sistema.

Las principales características que han dado éxito al sistema UNIX son: están escritas en C, interfaz de
usuario sencilla, sistema de ficheros jerarquizado, formato consistente para los archivos, contiene un
interfaz simple y consistente para los periféricos, es un sistema multiusuario y multiproceso, y oculta la
arquitectura de la máquina al usuario.

Existen diferentes distribuciones de UNIX: System V, BSD, OFS/1, SunOS, Solaris. En el capítulo se
describe brevemente la historia del sistema operativo UNIX.

2. En segundo lugar, se ha visto que la arquitectura del sistema operativo UNIX se puede dividir en
cuatro niveles o etapas. Una primera etapa, o nivel más interno, consiste en el hardware. En el segundo
nivel está el núcleo, que suministra los servicios que utilizan todos los programas de aplicación del
sistema UNIX. En el tercer nivel están los programas estándar y los ejecutables generados por el usuario.
En este nivel, un programa interactúa con el núcleo mediante las llamadas al sistema, que permite el
intercambio de datos, y dan instrucciones al núcleo para que realice operaciones con el hardware. En el
cuarto nivel están las aplicaciones que se sirven de otros programas ya creados ubicados en el nivel
inferior.

3. Los principales servicios realizados por el núcleo son: control de la ejecución de los procesos,
planificación de los procesos para su ejecución en la CPU, asignación de la memoria principal, protección
del espacio de direcciones de un proceso en ejecución, asignación de memoria secundaria para
almacenamiento y recuperación de los datos de usuario, regulación del acceso de los procesos a los
dispositivos periféricos, administración de archivos y dispositivos, tratamiento de interrupciones y
excepciones.

4. La ejecución de los procesos en un sistema UNIX está dividida en dos modos de ejecución: modo
núcleo o supervisor, y modo usuario. Un proceso que se ejecuta en modo usuario puede acceder sólo a
unas partes de su propio espacio de direcciones, pero no al espacio de direcciones de otros procesos, o

14
del mismo núcleo. Un proceso que se ejecuta en modo núcleo puede acceder al completo a su espacio
de direcciones y al del núcleo, pero no al de otros procesos.

Asimismo, los procesos en el sistema UNIX puede ser de tres tipos: procesos de usuario (se ejecutan en
modo usuario salvo cuando realizan llamadas al sistema, que se ejecutan en modo núcleo), procesos
demonio (no asociados a ningún usuario, se ejecutan en modo usuario y modo núcleo, realizan tareas
periódicas relacionadas con la administración del sistema), y procesos del núcleo (no asociados a ningún
usuario, se ejecutan exclusivamente en modo núcleo, pueden acceder directamente a los algoritmos y
estructuras de datos del núcleo sin hacer llamadas al sistema).

Los periféricos de E/S, el reloj del sistema, y los terminales pueden interrumpir a la CPU mientras se
ejecuta un proceso. El mecanismo de interrupciones notifica al núcleo que se ha completado una
operación o se ha producido un cambio de estado. Las interrupciones hardware son eventos asíncronos
que ocurren entre la ejecución de dos instrucciones de un proceso. Las interrupciones software o traps
son síncronas y se producen al ejecutar ciertas instrucciones especiales. Las excepciones se producen
durante el transcurso de ejecución de una instrucción, y son eventos síncronos inesperados, típicamente
errores. Dado que puede darse una petición de interrupción, mientras otra está siendo atendida, es
necesario asignar un nivel de prioridad de interrupción (npi) o nivel de ejecución del procesador. El npi
se almacena en un campo del registro de estado del procesador.

5. También, se estudia la estructura del sistema operativo UNIX, en la que se pueden distinguir tres
niveles: nivel de usuario, nivel de núcleo, y nivel de hardware.

En el nivel usuario, se encuentran los programas de usuario y los programas demonio. Interaccionan con
el núcleo usando las llamadas al sistema. Se puede realizar la invocación a las llamadas al sistema de dos
formas: mediante el uso de librerías de llamadas al sistema (similar a cualquier llamada de una función
C, las librerías de llamadas del sistema trasladas estas llamadas a las funciones primitivas necesarias que
permiten acceder al núcleo), y de forma directa.

En el nivel núcleo, se encuentra el subsistema de ficheros y el subsistema de control de procesos, que


interactúan con los programas de usuario a través de la interfaz de llamadas al sistema.

Asimismo, el nivel de núcleo se comunica con el nivel de hardware a través de su módulo de control del
hardware.

El subsistema de ficheros realiza todas las tareas del sistema asociadas a los ficheros (administra el
espacio en memoria principal y del sistema de ficheros, control el acceso a los ficheros, etc). La interfaz
que enlaza procesos con el subsistema de ficheros especifica el comportamiento y la semántica de todas
las llamadas al sistema pertinentes tales como open, close, read, write, stat, chown, chmod. La interfaz
exporta al usuario un pequeño número de abstracciones tales como: ficheros (ordinarios, enlaces
simbólicos, tuberías, ficheros de dispositivos), directorios, descriptores de ficheros, y sistemas de
ficheros. Los ficheros de dispositivos permiten a los procesos comunicarse con los dispositivos
periféricos. Existe los dispositivos modo bloque y modo carácter.

El subsistema de control de procesos se encarga de la sincronización, comunicación y planificación de


procesos, y administración de la memoria principal. Es el encargado de cargar los ficheros ejecutables en
la memoria principal. Algunas de las llamadas que emplea son: fork, exec, exit, wait, signal. Está formado
por tres módulos: módulo de administración de memoria (controla la asignación de memoria principal a
los procesos, mediante un proceso de intercambio o swapping, y transfiere algunos procesos de la
memoria principal a la secundaria cuando no se dispone de suficiente memoria principal), módulo de
planificación (asigna el uso de la CPU a los procesos), y el módulo de comunicación (mecanismos
asíncronos de señalización de eventos, transmisión síncrona de mensajes entre procesos).

15
El módulo de control de hardware es el responsable del manejo de las interrupciones y de la
comunicación con el hardware.

6. Por último, se estudia la interfaz de usuario para el sistema de ficheros. Un fichero es un contenedor
permanente de datos, y el núcleo suministra al usuario varias operaciones de control para nombrar,
organizar y controlar el acceso a los ficheros. Un directorio contiene información sobre el nombre de los
ficheros y directorios. UNIX organiza los ficheros en un árbol de directorios, que comienza en el
directorio raíz que se denota con “/”. La entrada de un fichero en un directorio constituye un enlace
duro para el fichero, que puede tener más de un enlace, en el mismo o en diferentes directorios.

Aparte del nombre de un fichero, el sistema de ficheros mantiene un conjunto de atributos para cada
fichero, almacenados en una estructura del disco conocida como nodo índice (nodo-i). Estos atributos
son: tipo de fichero, permisos e indicadores de modo, número de enlaces duros, tamaño del fichero,
identificador del dispositivo, número de nodo-i, identificador de usuario real (uid) y del grupo real (gid),
e información asociada al tiempo. Llamadas al sistema para conocer y manipular atributos de un sistema
son: stat y fstat, link y unlink, utimes, chown, chmod.

Además, cada fichero en UNIX tiene asociada una máscara de 16 bits conocida como máscara de modo
del fichero. Los bits 15-12 indican el tipo de fichero. El bit 11 es el bit _ISUID. Bit 10: _ISGID. Bit 9:
_ISVTX, y los bits 8-0 son los bits de acceso al fichero, que indican el tipo de permiso de acceso (lectura,
escritura, y ejecución). De estos 16, el propietario del fichero puede modificar únicamente los valores de
los bits 11 a 0, que se agrupa en cuatro dígitos octales M3M2M1M0.

El núcleo, cuando un usuario invoca a la llamada al sistema open para abrir un fichero, creo en memoria
principal una estructura de datos asociada al fichero abierto que se llama objeto de fichero abierto.
Cada objeto de fichero abierto se almacena en una entrada en una estructura global de núcleo
denominada tabla de ficheros. También, el núcleo asigna un descriptor de fichero, un número entero
positivo que sirve de identificador del objeto de fichero abierto. Cada proceso posee su propia tabla de
descriptores de procesos, que contiene todos los descriptores de procesos asociados a un determinado
proceso.

Los tres ficheros que ocupan las tres primeras entradas de la tabla de descriptores cuando se arranca un
proceso en UNIX son: fichero estándar de entrada (stdin), fichero estándar de salida (stout), y fichero
estándar de salida de mensajes de error (stdeer). El proceso pasa el descriptor de fichero a las llamadas
al sistema asociadas con operaciones de E/S.

El proceso pasa el descriptor del fichero a las llamadas al sistema asociadas con operaciones de E/S. El
núcleo usa el descriptor para localizar rápidamente el objeto de fichero abierto, de manera que el
núcleo sólo realiza una vez, y no en cada operación de E/S con el fichero, tareas tales como la búsqueda
de la ruta del acceso o el control de acceso al fichero, mejorando el rendimiento considerablemente.

En UNIX los ficheros son accedidos secuencialmente. Cuando un usuario abre el fichero, el núcleo
inicializa el puntero de lectura/escritura a cero. Si dos procesos abren el mismo fichero, el núcleo genera
un nuevo objeto de fichero abierto y un nuevo descriptor de fichero en cada invocación a open. Por otra
parte, un proceso puede duplicar un descriptor.

Las operaciones de E/S sobre un fichero son: apertura y cierre de un fichero (creat, open, close), lectura
y escritura (read, write), y acceso aleatorio (lseek). En el último apartado se estudia
pormenorizadamente estas funciones.

EJERCICIOS TEMA 1

16
17
TEMA 2: ADMINISTRACIÓN BÁSICA DEL
SISTEMA OPERATIVO UNIX
CONSIDERACIONES INICIALES

ACCESO AL SISTEMA

UNIX es multiusuario  los usuarios deben identificarse para acceder al sistema:

1. Usuario
2. Contraseña

UNIX distingue entre mayúsculas y minúsculas.

CONSOLAS VIRTUALES Y TERMINALES

Consola del sistema: monitor y teclado conectado directamente al sistem.

Consolas virtuales  más de una sesión de trabajo activa. Alt+Fx

La interfaz gráfica permite varias consolas virtuales en ventanas.

INTÉRPRETES DE COMAN DOS

Un intérprete de comandos – shell – es un programa de utilidad que permite al usuario comunicarse con
el sistema mediante órdenes o comandos escritas en la línea de órdenes, busca los programas
ejecutables asociados a las mismas y los ejecuta.

Formato:

nombre_orden -opciones parámetro1 … parámetroN

Donde:

 nombre_orden: nombre de un programa ejecutable.


 opciones: modifican el comportamiento de la orden.
 parámetros o argumentos adicionales.

El intérprete de comandos suspende su ejecución hasta que un programa termina y luego lee la
siguiente línea de órdenes.

[control+u] o clear  Borra todo el contenido de la línea de órdenes.

[control+w]  Borra una palabra de la línea de órdenes.

[control+c]  Interrumpe la orden actualmente en ejecución.

[control+z]  Suspende la orden actualmente en ejecución.

COMANDOS DE UNIX MÁS COMUNES

MANEJO DE DIRECTORIO S Y FICHEROS

18
CAMBIAR EL DIRECTORIO DE TRABAJO
El directorio de trabajo inicial es desde donde inicialmente empezará a trabajar el usuario cuando
accede al sistema.

El intérprete toma como referencia el directorio actual al ejecutar los comandos.

 cd ruta
 pwd
 cd ..
 cd –
 cd

OBTENER INFORMACIÓN DE UN DIRECTORIO O DE UN FICHERO


ls [-opciones] [fichero(s)]

Opción i: muestra el número de nodo-i de cada fichero.

CREAR DIRECTORIOS NUEVOS


mkdir dir1 dir2 … dirN

COPIAR FICHEROS
cp fichero1 fichero2 … ficheroN destino

Copia los permisos del original aplicando la umask del usuario que hace la copia.

MOVER FICHEROS
Mv fichero1 fichero2 … ficheroN destino

También se puede usar para cambiar de nombre un fichero.

BORRAR FICHEROS Y DIRECTORIOS


Rm fichero1 fichero2 … ficheroN

 -i pide confirmación.
 -r borra recursivamente
 rmdir borra un directorio si está vacío.

ACCEDER AL CONTENIDO DE LOS FICHEROS


 Mostrar el contenido del fichero pantalla a pantalla
 [espacio] para avanzar página
 [b] volver a página anterior
 [q] finaliza la ejecución

more fichero1 fichero2 … ficheroN

 Mostrar el contenido de golpe

cat fichero1 fichero2 … ficheroN

19
LA AYUDA DE UNIX

PÁGINAS DEL MANUAL DE AYUDA DE UNIX


man nombre

Puede haber un mismo nombre para un comando y un recurso del sistema. Las distintas páginas del
manual asociadas a un mismo nombre son secciones.

man sección nombre

MANUALES INFO
Libros o manuales que documentan algunos programas.

info [nombre_manual]

EDICIÓN DE FICHEROS

Invocamos un editor:

 nano
 vi
 gedit
 kwrite

SALIR DEL SISTEMA

 Salir de forma segura:

shutdown [OPTION] [TIME] [MESSAGE]

 Salir rápido y apagar:

halt

poweroff

 Reiniciar:

reboot

 Cerrar el terminal:

exit

[control+d]

GESTIÓN DE USUARIOS

CUENTAS DE USUARIO

Sistema multiusuario, cada usuario tiene su propia cuenta.

Cuenta especial root o superusuario, puede leer, modificar o borrar cualquier fichero en el sistema,
modificar permisos y ejecutar programas especiales.

20
sudo comando

sudo su

Los permisos de administración están configurados en /etc/sudoers.

Información de las cuentas de usuario en /etc/password:

 Nombre de usuario – login


 Identificador de usuario real – uid
 Identificador de grupo real – gid
 Contraseña – x – /etc/shadow
 Nombre real o completo del usuario
 Directorio de trabajo inicial
 Intérprete de comandos inicial

CREACIÓN Y ELIMINACIÓN DE UNA CUENTA DE USUARIO

El superusuario es el único que puede crear o eliminar una cuenta de usuario.

Se usa el programa useradd o adduser para crear una cuenta, y userdel o deluser para eliminarla.

Deshabilitar temporalmente una cuenta sin borrarla: colocar * delante de la clave encriptada de la línea
correspondiente en /etc/passwd.

MODIFICACIÓN DE LA INFORMACIÓN ASOCIADA A UNA CUENTA DE USUA RIO

El superusuario puede cambiar la información de usuario en /etc/passwd.

Cambio de contraseña de usuario:

passwd

Contraseña olvidada  superusuario debe modificarla.

GRUPOS DE USUARIOS

Cada usuario puede pertenecer a uno o más grupos. Afecta a los permisos sobre los ficheros.

Información de grupos: /etc/group.

 Nombre del gupo


 Clave encriptada de acceso a un grupo: /etc/shadow
 Gid
 Login de miembros del grupo

El superusuario modifica los grupos en /etc/group

CONFIGURACIÓN DE LOS PERMISOS DE ACCESO A UN FICHERO

MÁSCARA DE MODO SIMBÓLICA

S9 S8 S7 S6 S5 S4 S3 S2 S1 S0

 S9: tipo de fichero

21
o Ordinario –
o Directorio d
o Especial modo carácter c
o Especial modo bloque b
o FIFO o tubería p
o Enlace simbólico l
o Conector o socket s
 S8 S7 S6: propietario
o Lectura r
o Escritura w
o Varias cosas:
 S_ISUID y ejecución activados s
 S_ISUID activado y ejecución desactivado S
 S_ISUID desactivado y ejecución activado x
 S_ISUID y ejecución desactivados -
 S5 S4 S3: grupo
o Lectura r
o Escritura w
o Varias cosas:
 S_ISGID y ejecución activados s
 S_ISGID activado y ejecución desactivado S
 S_ISGID desactivado y ejecución activado x
 S_ISGID y ejecución desactivados -
 S2 S1 S0: otros
o Lectura r
o Escritura w
o Varias cosas:
 S_ISVTX y ejecución activados t
 S_ISVTX activado y ejecución desactivado T
 S_ISVTX desactivado y ejecución activado x
 S_ISVTX y ejecución desactivados –

La máscara de modo simbólica de un fichero puede también expresarse en modo octal.

CONFIGURACIÓN DE LA MÁSCARA DE MODO DE UN FICHERO

chmod {u,g,o,a} {+,-} {r,w,x,s,t} <ficheros>

chmod [M3M2M1M0] <ficheros>

SIGNIFICADO DE LOS PERMISOS

En el caso de ficheros:

22
 Lectura: ver contenido.
 Escritura: modificar o borrar el contenido, cambiar permisos, propietario y grupo.
 Ejecución: ejecución si es ejecutable.

En el caso de directorios:

 Lectura: lista el contenido.


 Escritura: crear, eliminar o renombrar archivos y directorios contenidos en el directorio,
independientemente de los permisos de los ficheros.
 Ejecución: entrar a la carpeta.

CONSIDERACIONES ADIC IONALES

El acceso a un fichero depende de la máscara de modo del fichero y de los permisos de la ruta.

CONSIDERACIONES GENERALES SOBRE LOS INTÉRPRETES DE COMANDOS

TIPOS DE INTÉRPRETES DE COMANDOS

 Bourne
 C

En GNU/Linux:

 Bash - /bin/bash
 Tcsh - /bin/tcsh – versión extendida de C.

CARACTERES COMODINES

Los caracteres comodines permiten referirse a más de un fichero a la vez.

 *.- cualquier carácter o cadena (sustitución de * en nombres de ficheros  expansión de


comodines).

$ echo D*

$ echo D*

 ?.- expande un único carácter.


 [].- sustituye a los caracteres incluidos dentro del paréntesis.

$ echo *[sS] #ficheros que empiecen por s ó S.

REDIRECCIÓN DE ENTRADA/SALIDA

 >.- redirige la salida estándar a un fichero, si no existe se crea. Reemplaza el contenido.


 >>.- redirige la salida estándar a un fichero, si no existe se crea. Concatena con contenido
anterior.
 <.- redirige la entrada estándar.

ENCADENAMIENTO DE ÓR DENES

 ;.- separar órdenes para escribirlas en una misma línea.


 |.- tubería. La salida del primero será la entrada del segundo.

23
ASIGNACIÓN DE ALIAS

Nombre alternativo o alias.

Alias nombre=’definición’

Alias

Unalias nombre_alias

Únicamente existirá mientras continúe abierta la sesión.

SHELL SCRIPTS

Ficheros de texto con programas en el lenguaje del intérprete de comandos.

Ventajas: portabilidad.

Desventajas: lentitud de ejecución y visible a cualquier usuario con permisos.

# comentarios

#! /bin/bash

FUNCIONAMIENTO DE UN INTÉRPRETE DE COMAN DOS

Órdenes internas

Órdenes externas

VARIABLES DEL INTÉRP RETE DE COMANDOS Y VARIABLES DE ENTORNO

Ver variables disponibles: set

Echo $variable

Consultar variable ? para ver código de retorno de una ejecución.

VARIABLES DE ENTORNO

Proceden del entorno del proceso asociado al intérprete.

Ver variables de entorno: env

Cambios en variable de entorno: export

Exportado automático: set -a $variable

Borrar variables de entorno: unset

Los cambios, las definiciones y las exportaciones de variables del intérprete desaparecen al cerrar el
intérprete. Para hacer persistentes: incluir en los ficheros de arranque del intérprete.

LA VARIABLE DE ENTORNO PATH

Rutas de acceso a los directorios donde el intérprete buscará el fichero asociado a una orden externa.

24
Ruta1:ruta2:…:rutaN

Añadir nueva ruta:

PATH=ruta_nueva:$PATH

PATH=$PATH:ruta_nueva

DEPURACIÓN EN BASH

Si el comando no tiene salida, se produce un error o la variable no existe, bash falla silenciosamente.

Usar echo.

Opción de depuración: set -x, set +x, bash -x

Convención de fin de línea

 Windows: CR+LF
 UNIX: LF

CONTROL DE TAREAS

VISUALIZACIÓN DE LOS PROCESOS EN EJECUCI ÓN


Ps

Ps aux

Top`

jobs

PRIMER PLANO Y SEGUN DO PLANO


Añadir & al final de la orden para segundo plano.

/dev/null agujero negro

Relanzar una tarea en primer plano: fg

Relanzar en segundo plano: bg

ELIMINACIÓN DE PROCE SOS

Kill – por defecto envía señal SIGTERM

Killall nombre_proceso

Pkill nombre_proceso

OTROS COMANDOS DE UNIX

INFORMACIÓN DEL SISTEMA

Date. Fecha hora actuales.

25
Cal. Calendario.

Uptime. Tiempo que lleva encendida la máquina.

Who/w. usuarios conectados.

Who am I/whoami. Nombre mi usuario.

Finger usuario. Info del usuario.

Uname -a. info sobre núcleo.

Cat /proc/cpuinfo. Info sobre CPU.

Cat /proc/meminfo. Info sobre memoria.

Cat /proc/PID/status. Info del proceso PID.

Df. Espacio libre en discos.

Du. Espacio usado por los directorios.

Free. Uso de memoria principal y espacio de intercambio.

Whereis app. Localiza ejecutable app.

Which app. Localiza el comando app.

BÚSQUEDA DE FICHEROS Y TEXTO

FIND ARCHIVO
Desde el directorio actual o especificar.

Op -l da más info.

Admite expresiones regulares.

GREP
Grep patrón fichero1 fichero2 … ficheroN

Busca una cadena de texto dentro de uno o varios ficheros.

COMPRESIÓN DE FICHER OS

TAR
tar cf fichero.tar f1 f2 fN. Empaqueta los ficheros f1, f2,..,fN en el fichero fichero.tar.

tar xf fichero.tar. Extrae el contenido de fichero.tar.

tar czf file.tar.gz f1 f2 fN. Empaqueta y comprime con el programa gzip los ficheros f1, f2,..,fN en el
fichero file.tar.gz.

26
tar cjf file.tar.bz2 f1 f2 fN. Empaqueta y comprime con el programa bzip2 los ficheros f1, f2,..,fN en el
fichero file.tar.gz.

tar xzf file.tar.gz. Extrae y descomprime usando el programa gzip el contenido de file.tar.gz.

tar xjf file.tar.bz2. Extrae y descomprime usando el programa bzip2 el contenido de file.tar.bz2.

COMPRESIÓN SIN TAR


gzip fichero. Comprime fichero y lo renombra como fichero.gz.

gzip -d fichero.gz. Descomprime fichero.gz a fichero.

INSTALACIÓN DE SOFWA RE

PRESENTACIÓN EN CÓDI GO FUENTE


Código fuente en .tar.gz, descomprimir y ejecutar. Añadir a PATH.

Compilador C: gcc

Comando configure

Make compila el código fuente

Make install para instalar

No todos los programas usan configure y make.

Instalar en /usr/local o en /opt para que todos los usuarios tengan acceso al programa.

PRESENTACIÓN EN PAQU ETE


Paquetes de la distribución Red Hat y derivados. Rpm -i paquete.rpm

Paquetes de la distibución Debian. Dpkg -i paquete.deb. apt. apt-get

Paquetes de la distribución Slackware. .tgz. seleccionar paquete con pkgtool. Instalar con installpkg.

Repositorio: almacén de distribución de software.

TRABAJO EN RED

Acceder a un sistema remoto: tener cuenta, accesos remotos permitidos, conocer su IP o nombre.

Saber si un sistema es accesible por su nombre: /etc/hosts

Dominio registrado en DNS.

Sistema accesible? Ping

Información sobre un sistema: nslookup

Conexión remota: ssh (telnet, rlogin o remsh). Ssh es cifrado.

Copiar archivos entre sistemas: scp o rcp (inseguro).

27
Transferir archivos: sftp o ftp (insegura).

El sistema puede admitir o no conexiones remotas de tipo anónimo.

Enviar y recibir correo: mail, mailx o elm. usuario@host.

EJEMPLOS ADICIONALES DE SHELL SCRIPTS

`comando` o $(comando). Sustitución de comandos.

While [condición]

Do

Done

Operación aritmética entera: $((operación)). `expr $cont + 1`.

Operaciones con coma flotante  herramientas externas, bc.

Case $variable in

Valor) orden;;

*) orden;; //default

Esac

Cut -c

Recuperar parámetros: $#

If [condición]

Then

Orden

Else

Fi

For ((n=1; n<=10; n++))

Do

Orden

Done

kill -9 $! > /dev/null # Se mata el ultimo proceso en background

function función () {}

FICHEROS DE ARRANQUE DE UN INTÉRPRETE DE COMANDOS

Tipos de intérpretes:

28
 Intérprete de entrada – login shell
 Intérprete interactivo – interactive shell
 Intérprete no interactivo – non-interactive shell

Bash al ser invocado ejecuta los comandos del fichero /etc/profile

~/.bash_profile

~/.bash_login

~/.profile

--noprofile al llamar a bash

Terminar: lee y ejecuta ~/.bash_logout.

Para intérprete interactivo:

~/.bashrc

/etc/bashrc antes a veces. Evitarlo –norc

--rcfile fichero. Fuerza a usar otro fichero.

No interactivo, busca BASH_ENV y expande

if [ -n "$BASH_ENV" ]; then . "$BASH_ENV"; fi

LA FUNCIÓN DE LA LIBRERÍA SYSTEM

Ejecutar desde un programa ejecutable una orden del intérprete de comandos.

#include <stdlib.h>

int system (const char *orden);

Si la invocación a /bin/sh falla, el valor devuelto por system es 127.

RESUMEN TEMA 2

En este capítulo se describen algunos de los principales trabajos asociados con la administración del
sistema UNIX, tales como gestión de usuarios, configuración de los permisos de acceso a los ficheros y el
control de tareas.

1. Para poder acceder al sistema, se requiere un proceso de identificación que consta de la introducción
del nombre de usuario (login) y de la contraseña de acceso (password).

La consola del sistema es el monitor y teclado conectados directamente al sistema. UNIX cuenta con
acceso a consolas virtuales que permite más de una sesión de trabajo activa. Para acceder a la consola i:
Alt + Fi.

Un intérprete de comandos (shell) es un programa de utilidad que permite al usuario comunicarse con
el sistema. Lee las órdenes o comandos que teclea el usuario, busca los programas ejecutables
asociados, y los ejecuta. El formato general es nombre_orden –opciones parámetro
parámetro2…..parámetroN

29
Las opciones modifican el comportamiento por defecto de la orden. Los parámetros o argumentos
aportan información adicional que usará la orden.

2. Los comandos de uso más común en UNIX se pueden clasificar por:

Manejo de directorios y ficheros: cambiar el directorio de trabajo (cd); conocer la ruta absoluta del
directorio de trabajo actual (pwd); obtener información de un fichero o directorio (ls
[opciones][fichero(s)]); crear nuevos directorios (mkdir dir1 dir2…dirN); copiar ficheros (cp fichero 1
fichero2…ficheroN destino); mover ficheros (mv fichero 1 fichero2…ficheroN destino); borrar ficheros y
directorios (rm fichero 1 fichero2…ficheroN), acceder al contenido de los ficheros (more/cat fichero1
fichero2…ficheroN) donde more muestra el fichero pantalla a pantalla mientras que cat lo muestra
entero de una vez.

Para acceder a las páginas del manual de ayuda de UNIX se emplea la orden man. Para especificar una
determinada sección, se debe invocar man seccion.

Para editar un fichero, se puede invocar desde la línea de comandos a alguno de los editores ( p. ej. vi o
nano). Otros editores se acceden a través de la interfaz gráfica X como por ejemplo gedit o kwrite.

Para salir del sistema de forma segura se usa el comando shutdown. Los comandos halt o poweroff
apagan también la computadora, y para reiniciar se usa reboot. Para cerrar únicamente el intérprete de
órdenes se teclea exit.

3. También se vio como el usuario root o superusuario es el único usuario del sistema UNIX que puede
leer, modificar o borrar cualquier fichero en el sistema. Puede cambiar permisos y ejecutar programas
especiales. Esta cuenta debe ser usada exclusivamente por el administrador del sistema. El carácter “#”
es el marcador de la línea de comandos que indica al usuario si está en la cuenta root. El sistema
almacena información sobre las cuentas de usuario en el fichero /etc/passwd, que contiene información
sobre: nombre de usuario, identificador de usuario real (uid), identificador de grupo real (gid),
contraseña, nombre real del usuario, directorio de trabajo inicial, e intérprete de comandos inicial.

El superusuario crea una nueva cuenta de usuario con el programa useradd o adduser, y para eliminarla
usa userdel o deluser. Para deshabilitar temporalmente la cuenta sin borrarla, se coloca el carácter “*”
delante de la clave cifrada de la línea correspondiente del fichero /etc/passwd.

El superusuario puede cambiar la información asociada a una cuenta de usuario a través del fichero
/etc/passwd.

Cada usuario puede pertenecer a uno o más grupos, que le da ciertos permisos de acceso a un fichero.
El fichero /etc/group contiene información acerca de los grupos de usuarios existentes en el sistema con
la siguiente información: nombre del grupo, clave encriptada de acceso a un grupo, gid y el login de
otros usuarios del grupo. La clave de acceso no se suele usar, y en dicho campo se escribe ‘*’, o ‘x’, que
indica que la contraseña se encuentra en /etc/shadow.

El superusuario puede añadir nuevos usuarios a un cierto grupo, y puede añadir nuevos grupos con los
comandos addgroup o groupadd.

4. La máscara de modo simbólica es una cadena de caracteres que muestra información sobre la
máscara de modo del fichero, de estructura s9s8s7s6s5s4s3s2s1s0, que se obtiene al ejecutar la orden ls
-l. Cada carácter tiene un significado: s9 indica el tipo de fichero, s8 y s7 indican si están habilitados los
permisos de lectura y escritura para el propietario del fichero; s6 da información sobre el bit S_IUID; s5 y
s4 indican si están habilitados los permisos de lectura y escritura para los miembros del grupo; s3 da

30
información sobre el bit S_ISGID; s2 y s1 dicen si están habilitados los permisos de lectura y escritura
para el resto de usuarios, y s0 informa sobre el bit S_ISVTX.

Para modificar la máscara: chmod{u,g,o,a} {+,-}{r,w,x,s,t} <ficheros>.

Aunque un fichero tenga la máscara de modo –rwxrwxrwx, los usuarios no podrán acceder a él a menos
que también tengan permiso de lectura y ejecución para el directorio donde se encuentra el fichero.

5. Los intérpretes de comandos más importantes son Bourne y C. El nombre del intérprete de Bourne es
sh, y el de C en la mayoría de las distribuciones es csh, con ruta de acceso /bin/csh.

La mayoría de los intérpretes de comandos tienen la capacidad de referirse a más de un fichero usando
comodines tales como ‘*’, ‘?’, o ‘[]’.

Para cambiar la entrada y la salida estándar, se emplea un mecanismo de entrada/salida. Para redirigir
la salida de una orden hacia un fichero se usa el carácter ‘>’ seguido por el fichero de salida. Para
redirigir la salida estándar se usa el carácter ‘<’ seguido del nombre del fichero de entrada.

Se pueden escribir varias órdenes en una misma línea escribiendo ‘;’ entre ellas. Para conseguir que la
salida de una orden se convierta en la entrada de otra orden, se emplea una tubería con el símbolo ‘|’.

Los alias son nombres alternativos a un comando que sustituyen el nombre verdadero. Para definir un
alias se emplea el comando alias, y para borrarlo, unalias.

Los shell scripts son ficheros de texto que contiene programas escritos en el lenguaje del intérprete
comando, que incluye definición de variables y funciones, y el uso de sentencias de if, while, for, etc. Las
ventajas de los shell scripts son su portabilidad, y su facilidad de lectura e interpretación. En cambio,
comparado con un programa compilado, es lento de ejecución, y el código es visible a cualquier usuario.

Los shell scripts se encabezan con comentarios que indican el nombre del archivo y lo que hace. Los
comentarios se insertan anteponiendo el carácter ‘#’. La primera línea comienza con ‘#!’ y la ruta de
acceso del nuevo intérprete de comandos con se ejecutará el script.

El fichero de texto donde se escriba el shell script debe tener permiso de ejecución para el usuario. Para
saber si tiene permiso, se deje consultar la máscara de modo simbólica con ls -1, y modificarle, en el su
caso, con chmod.

6. Un intérprete de comandos es un fichero ejecutable. Las órdenes que se pueden ejecutar en un


intérprete de comandos pueden ser: órdenes internas (builtin commands), cuyo código de ejecución se
encuentra incluido dentro del propio código del intérprete. Su ejecución no supone la creación de un
nuevo proceso (ej: cd, pwd); y órdenes externas, que requieren de la búsqueda y ejecución del fichero
ejecutable asociado a cada orden. Son programas ejecutables o shell scripts incluidos en la distribución
del sistema, y suponen la creación de al menos un proceso nuevo (ej: ls, mkdir).

7. Las variables del intérprete de comandos son un conjunto de variables que se crean al ejecutar un
intérprete de comandos. Estas variables son locales al intérprete y pueden ser utilizadas por todas sus
órdenes internas. El comando set muestra todas las variables disponibles.

Para conocer el valor de una determinada variable, se usa el comando echo $variable. Se puede
modificar el valor de una variable empleando el signo ‘=’.

Las variables de entorno son las variables del intérprete de comandos que proceden del entorno del
proceso asociado al intérprete. Ej: UID es una variable de entorno, es de sólo lectura y especifica el
identificado del usuario real del usuario. El comando env visualiza el listado de las variables de entorno.
31
Los cambios que se hacen en una variable de entorno no se pasan al entorno del proceso hasta que el
usuario no exporta explícitamente dicha variable al entorno, mediando el comando export variable.

La variable de entorno PATH especifica las rutas de acceso a los directorios donde el intérprete debe
buscar el fichero ejecutable asociado a una determinada orden externa. Para añadir una nueva ruta:
PATH= ruta_nueva:$ PATH.

8. Cada proceso que se ejecuta por un usuario es una tarea para el sistema. El control de tareas es una
utilidad que permite controlar el estado de las diferentes tareas que se están ejecutando en el sistema.

El comando ps muestra la lista de procesos que el usuario está ejecutando actualmente. Si se añado la
opción –aux se muestra también la utilización del procesador y de la memoria.

El comando top muestra la ocupación en tiempo real de cada proceso, y se actualiza cada 5 segundos.

El comando jobs permite chequear el estado de un proceso.

Un proceso puede estar en primer plano o en segundo plano. El proceso en primer plano es el que
interactúa con el usuario. El proceso en segundo plano no recibe ninguna señal desde el teclado, se
ejecuta en silencio sin necesidad de interacción. Para ejecutar una tarea en segundo plano se añade el
carácter ‘&’ al final de la orden. Los procesos también pueden ser suspendidos, e interrumpirlos.

Para eliminar un proceso, se usa el comando kill, y toma como argumento el pid del proceso o el
número de tarea que tenga asignado o pkill y el nombre del proceso.

Existen herramientas para trabajar en red como ssh o scp que permiten trabajar en computadores
remotos de forma similar al computador local y numerosas utilidades que están pensadas para ser usas
en la línea de órdenes.

Bash es un lenguaje de script completo que permite realizar todo tipo de cosas (funciones, bucles, paso
de parámetros como argumentos de entrada entre otras muchas, su sintaxis es tersa y a veces difícil de
depurar pero se trata de un lenguaje muy potente para manejar archivos y procesos.

La sesión puede configurarse mediante ficheros de configuración como puede ser /etc/profile,
~/.bash_profile, ~/.bash_login, y ~/.profile entre otros.

Finalmente, dada la utilidad de los comandos del sistema, la función de librería system permite invocar
comandos del sistema desde el lenguaje C. El paso contario ejecutar programas escritos en c desde bash
es inmediato (basta con compilarlos y llamar al ejecutable. (La forma de crear programas que puedan
aceptar parámetros se explicará en el Ejemplo 3.4).

EJERCICIOS TEMA 2

32
TEMA 3: ESTRUCTURAS DE DATOS DE
CONTROL DE PROCESOS EN UNIX
INTRODUCCIÓN

Una región o segmento es un subconjunto o área de direcciones contiguas de memoria virtual. En


cualquier programa se distinguen al menos tres regiones: código o texto, datos y pila.

Proceso padre invoca fork y crea proceso hijo. El hijo hereda su contexto de ejecución: código, datos y
pila.

Los procesos son unidades funcionalmente independientes.

Se presenta el modelo clásico del SVR3, las versiones modernas de UNIX presentan diferencias.

ESPACIO DE DIRECCIONES DE MEMORIA VIRTUAL ASOCIADO A UN PROCESO

FORMATO LÓGICO DE UN ARCHIVO EJECUTABLE

Cuatro partes:

 Cabecera primaria:
o Número mágico: entero pequeño que identifica el tipo de archivo ejecutable.
o Número de secciones.
o Dirección virtual de inicio de ejecución del proceso.
 Cabeceras de las secciones: tipo y tamaño de sección; y la dirección virtual de comienzo de
sección.
 Secciones: contienen el código, datos inicializados (estáticas) y no inicializados (bss).
 Otras informaciones: tabla de símbolos y otros. Tabla de símbolos del compilador: variables,
nombres de funciones, tipos, constantes, etc; almacena nombre, tipo, dirección de memoria,
etc. Tabla hash.

REGIONES DE UN PROCE SO

Una llamada a exec carga en memoria un fichero ejecutable. El espacio de direcciones de memoria
virtual, o espacio de direcciones de usuario, asignado por el compilador será traducido por el núcleo a
direcciones de memoria real.

Regiones del espacio de direcciones de memoria virtual:

 Regiones de código y de datos, del ejecutable.


o Código.
o Región de datos inicializados o zona estática de la región de datos. Tamaño fijo.
o Región de datos no inicializados o zona dinámica de la región de datos. Varía durante
la ejecución.
 Región de pila o pila de usuario.
o Tamaño ajustado dinámicamente en tiempo de ejecución.
o Constituída por marcos de pila, se añaden al llamar a una función y se extraen al
terminar. Un marco contiene los parámetros de la función, variables locales y
direcciones a el contador del programa o al puntero de pila.

33
o Registro especial de puntero de pila (próxima entrada libre o última utilizada) y la
dirección de crecimiento, altas o bajas.

Existe otra parte del espacio de direcciones virtuales de un proceso: el espacio del núcleo.

 Área de usuario o área U.


 Pila del núcleo.

Son locales a un proceso pero propiedad del núcleo y sólo él las manipula.

OPERACIONES CON REGI ONES IMPLEMENTADAS POR EL NÚCLEO

Estructura local del núcleo: tabla de regiones por proceso.

 Información relevante de regiones de código, datos y pila del proceso. Y memoria compartida.
 Cada entrada contiene un puntero a la tabla de regiones.

Estructura global del núcleo: tabla de regiones.

 Se organiza en dos listas:


o Lista enlazada de regiones libres.
o Lista enlazada de regiones activas.

Operaciones con regiones implementadas por el núcleo:

1. Bloquear y desbloquear una región mientras trabaja.


2. Asignar una región.
a. Algoritmo allocreg(). Elimina la primera entrada disponible de la lista enlazada de
regiones libre y la sitúa en la lista de regiones activas.
b. Llamadas: fork exec y shmget.
3. Ligar una región al espacio de direcciones virtuales de un proceso.
a. Algotitmo attachreg().
b. Llamadas: fork, exec, shmat.
4. Cargar una región con el contenido de un fichero.
a. Algoritmo loadreg().
b. Llamada exec.
5. Desligar una región del espacio de direcciones de un proceso.
a. Algoritmo detachreg().
b. Llamadas: exec, exit y shmdt.
6. Liberar una región.
a. Algoritmo freereg(). Devuelve una región a la lista de regiones libres.
7. Duplicar una región.
a. Algoritmo dupreg().
b. Llamada fork.

IDENTIFICADORES NUMÉRICOS ASOCIADOS A UN PROCESO

IDENTIFICADOR DEL PROCESO

Cada proceso tiene asignado un entero positivo que lo identifica: PID = {0, …, PIDmax}.

Sistema operativo arranca  crea proceso 0 (0)  genera un hijo: proceso inicial (1)  PID 0 se
transforma en el proceso intercambiador (swapper)  PID 1 será el padre de todos los demás procesos.

34
 salida=getpid(); Devuelve PID o -1.
 salida=getppid(); Devuelve PID del padre o -1.

IDENTIFICADORES DE U SUARIO Y DE GRUPO

Cada proceso tiene dos identificadores enteros positivos de usuario y otros dos de grupo:

 Identificador de usuario real – uid – identifica al ejecutor del proceso


 Identificador de usuario efectivo – euid – identifica al propietario de los nuevos ficheros
 Identificador del grupo real – gid
 Identificador del grupo efectivo – egid

Usuario root: uid=0 y gid=0.

Normalmente uid y euid van a coincidir.

Si el bit S_ISUID está activado, euid tomará el valor del propietario del fichero y no del usuario que lo
está ejecutando.

Esto concede al ejecutor los privilegios del creador en cuanto a permisos de usuario. Ej.: abrir ficheros.

Obtener valores de los identificadores de usuario: getuid, geteuid, getgid y getegid.

Cambiar los valores: setuid, setgid, seteuid, setegid.

salida = setuid (par); Devuelve 0 o -1. Asigna par a uid y euid.

Ejemplos de programas que hacen uso de de setuid y setgid: login, sudo o passwd. Acceden a ficheros
protegidos, propiedad de root, para poder manipularlos necesitan escalar sus privilegios en la ejecución
de los programas, para ello está el S_ISUID activado en el fichero de los programas y se cambia el
usuario efectivo al del propietario, root.

ESTRUCTURAS DE DATOS DEL NÚCLEO ASOCIADAS A LOS PROCESOS

Estructura Propietario Ubicación Local/Global


Código del proceso Proceso Proceso Local

Datos del proceso Proceso Proceso Local

Pila del proceso Proceso Proceso Local

Pila del núcleo Núcleo Proceso Local

Área U Núcleo Proceso Local

Tabla de regiones por Núcleo Núcleo Local


proceso
Tabla de procesos Núcleo Núcleo Global

Tabla de regiones Núcleo Núcleo Global

Tablas de páginas Núcleo Núcleo Global

Tabla de descriptores de Núcleo Área U Local


ficheros

35
PILA DEL NÚCLEO

Necesaria al existir modo usuario y modo núcleo de ejecución.

La pila del núcleo es una estructura local a cada proceso que contiene los marcos de pila de las
funciones o rutinas del núcleo invocadas durante la ejecución del proceso en modo núcleo.
Implementada dentro del área U o en un área independiente. Vacía en modo usuario.

Un proceso que invoca a una llamada al sistema en reaidad está invocando a la función de librería
asociada a dicha llamada al sistema  entre otras, posee una instrucción de interrupción software o
trap, que produce la conmutación hardware al modo núcleo.

Estructura de marco:

 Variables locales.
 Dirección de comienzo del macro de pila anterior (copia de registro de puntero de pila).
 Dirección de retorno despues de la ejecución de la función (copia de registro de contador de
programa).
 Parámetros.

Hay un marco 0 usado para inicializar la pila, marco mudo.

TABLA DE PROCESOS

La tabla de procesos es una estructura global del núcleo donde cada entrada contiene información de
un determinado proceso:

 PID.
 Identificadores de usuario del proceso: uid, euid, gid, egid.
 Punteros a la tabla de regiones por proceso y al área U.
 Estado del proceso.
 Punteros para enlazar a los procesos en diferentes listas (procesos planificados para ejecución
o procesos dormidos).
 Canal o dirección de dormir.
 Información asociada a la prioridad de planificación del proceso.
 Información asociada al tratamiento de las señales.
 Información genealógica (pid del padre, puntero al primer hijo creado, al último, etc.).
 El tiempo de ejecución del proceso y el tiempo de utilización de los recursos de la máquina
para el cáulculo de prioridad de planificación.

ÁREA U

El área U es una estructura local de cada proceso con información de control del proceso para el núcleo:

 Puntero a la tabla de procesos del proceso.


 Identificadores de usuario del proceso: uid, euid, gid, egid. Pueden diferir de los de la tabla de
procesos.
 Argumentos de entrada, valores de retorno e identificador de error de la llamada en ejecución.
 Las direcciones de los manipuladores de señales.
 Información de las regiones de código, datos y pila, desde la cabecera del programa.
 Tabla de descriptores de ficheros (abiertos por el proceso).
 Terminal asociado.

36
 Estadísticas de uso de la CPU.

El núcleo referencia a una variable denominada u para acceder al área U del proceso actualemente en
ejecución, si se cambia de proceso, se cambia u.

TABLA DE REGIONES POR PROCESO

La tabla de regiones por proceso es una estructura local a cada proceso con una entrada por cada región
del proceso.

Cada entrada apunta a la región en la tabla de regiones y mantiene el tipo de acceso permitido para el
proceso.

Puede implementarse dentro de la entrada de la tabla de procesos asociada a dicho proceso, dentro del
área U o de forma independiente.

TABLA DE REGIONES

La tabla de regiones es una estructura global del núcleo con una entrada por cada región asignada:

 Puntero al nodo-i del fichero cargado en la región.


 Tipo de región (código, datos, pila de usuario o memoria compartida).
 Tamaño.
 Localización  puntero a una tabla de páginas.
 Estado de la región, combinación de bloqueada, bajo demanda, cargando en memoria y válida.
 Contador de referencias.

Se organiza en dos listas:

 Lista enlazada de regiones libres.


 Lista enlazada de regiones activas.

37
CONTEXTO DE UN PROCESO

DEFINICIÓN

El contexto de un proceso en un cierto instante de tiempo se puede definir como la información


relativa al proceso que el nucleo debe conocer para poder iniciar o continuar su ejecución.

Cuando el núcleo pasa a ejecutar otro proceso debe cambiar de contexto.

El contexto de un proceso está formado por:

 Contexto a nivel de usuario:


o Código, datos, pila de usuario y memoria compartida.
 Contexto de registros de la máquina:
o Contador del programa: siguiente instrucción CPU.
o Registro de estado del procesador: modo de ejecución, nivel de prioridad de
interrupción, indicador de rebose, indicador de arrastre, etc.
o Puntero de la pila de usuario.
o Registros de propósito general: registro 0 y registro 1 simplificando.
 Contexto a nivel del sistema:
o Entrada de la tabla de procesos asociada a dicho proceso.
o Área U.
o Pila del núcleo.
o Tabla de regiones por proceso.
o Entradas de la tabla de regiones.
o Tablas de páginas asociadas a las entradas de la tabla de regiones.

PARTE ESTÁTICA Y PARTE DINÁMICA DEL CONTEXTO DE UN PROCESO

Parte dinámica  capa de contexto: contexto de registros, pila de núcleo y pila de capas de contexto.

Parte estática: todo lo demás.

38
La capa de contexto puede variar durante el tiempo de vida del proceso.

Pila de capas de contexto  manipulación de las capas de contexto que hace el núcleo. Área U.

Área U:

 PCB – bloque de control de proceso.


 Puntero al proceso.
 UIDs de proceso.
 Información de las llamadas al sistema.
 Manejadores de error e informaciones asociadas.
 Información de la cabecera del programa.
 Descriptores de ficheros abiertos.
 Terminales asociados al proceso.
 Estadísticas.
 Pila del núcleo asociada al proceso.

El núcleo almacena en la entrada de la tabla de procesos asociada al proceso en ejecución la


información necesaria para localizar al capa de contexto superior de la pila de capas de contexto
asociada al proceso.

Se añade una capa de contexto a la pila cuando:

 Interrupción.
 Proceso realiza una llamada al sistema.
 Cambio de contexto.

Se extrae una capa cuando:

 Termina la gestión de una interrupción.


 Vuelve a modo usuario tras completar llamada al sistema.
 Cambio de contexto.

Número de capas de contexto limitado por el número de niveles de interrupción que soporte la
máquina =una capa por nivel de interrupción, una para las llamadas al sistema y otra para el nivel de
usuario.

SALVAR Y RESTAURAR E L CONTEXTO DE UN PROCESO

Se entiende por salvar el contexto de un proceso a la acción del núcleo de añadir una capa de contexto
en la pila de capas de contexto asociada a dicho proceso.

Asimismo se entiende por restaurar el contexto de un proceso a la acción del núcleo de extraer la capa
superior de la pila de capas de contexto asociada a dicho proceso e inicializar el contexto de registros y
la pila del núcleo con los valores que se habían salvado en dicha capa.

Estas operaciones se implementan por hardware o microcódigo.

Vuelta abortiva, el núcleo aborta su secuencia de ejecución actual, restaura la capa salvada del área U y
reinicia su ejecución dentro del contexto restaurado.

Algoritmo setjmp() para salvar una capa de contexto en el área U.

39
Algoritmo longjmp() para extraer la última capa salvada e inicializar el contexto de registros y la pila del
núcleo.

No confundir estos algoritmos con la funciones de librería del mismo nombre, aunque su utilidad es
parecida.

CAMBIO DE CONTEXTO

Se define el cambio de contexto como el conjunto de tareas que debe realizar el núcleo para aplazar o
finalizar la ejecución del proceso (A) actualmente en ejecución, y comenzar o continuar con la ejecución
de otro proceso (B).

Motivos para cambiar de contexto:

 La entrada de un proceso en el estado dormido.


 La finalización de la ejecución de una llamada al sistema exit.
 La vuelta al modo usuario tras ejecutarse una llamada al sistema y la existencia de un proceso
esperando para ser ejecutado con mayor prioridad de planificación que el actual.
 La vuelta al modo usuario tras atenderse una interrupción y la existencia de un proceso
esperando para ser ejecutado con mayor prioridad que el actual.
 La finalización del tiempo de uso de procesador de un proceso ejecutándose en modo usuario.

Tareas del algorítmo del núcleo de cambio de contexto:

 Decidir si hay que hacer un cambio de contexto, de acuerdo con las circunstancias que lo
motivan expuestas anteriormente, y si puede realizarse en el instante actual.
 Salvar el contexto del proceso actual (A).
 Usar el algoritmo de planificación de procesos para elegir el próximo proceso (B) cuya
ejecución se va a iniciar o se va a continuar.
 Restaurar el contexto del proceso (B) que ha sido elegido para ser ejecutado.

TRATAMIENTO DE LAS INTERRUPCIONES

Las interrupciones (hardware o software) son atendidas en modo núcleo dentro del contexto del
proceso que se encuentra actualmente en ejecución, aunque dicha interrupción no tenga nada que ver
con la ejecución de dicho proceso.

Niveles de prioridad de interrupción:

 npi – nivel de prioridad de interrupción actual almacenado en el registro de estado del


procesador.
 npii – nivel de prioridad asociado al tipo de interrupción.

Algoritmo inthand(): cuando npii > npi

 Salvar el contexto del proceso actual.


 Elevar el nivel de prioridad de interrupción.
 Obtener el vector de interrupción. El número del vector de interrupción se utiliza como un
índice en la tabl de vectores de interrupción que almacena un puntero al manejador o rutina de
servicio apropiada para la interrupción.
 Invocar al manipulador o rutina de servicio de la interrupción.
 Restaurar el contexto del proceso y el npi.

40
Las que no tienen suficiente prioridad para ser atendidas pasan a pila de interrupciones o a pila del
núcleo.

El tiempo utilizado para atender la interrupción se carga al cuanto del proceso.

El contexto del proceso no es protegido del manejador de la interrupción.

INTERFAZ DE LAS LLAMADAS AL SISTEMA

Las llamadas al sistema son el mecanismo que los procesos de usuario utilizan para solicitar al núcleo el
uso de los recursos del sistema.

Un proceso invoca una llamada al sistema como a una función de librería más.

Compilador C  Librería C.

Las funciones de librería ejecutan un trap del sistema operativo.

La ejecución de un trap detiene la ejecución del proceso, pasa el procesador a modo núcleo y ejecuta
código instalado por el SO en una posición conocida de la memoria. El núcleo invoca el algoritmo
syscall().

El algoritmo del núcleo syscall() para el tratamiento de las llamadas al sistema requiere de un único
parámetro de entrada que le es pasado por la función de librería, el identificador numérico de la
llamada al sistema.

Algoritmo syscall():

1. Encontrar en la tabla de llamadas al sistema la dirección de comienzo de la rutina del núcleo


asociada a la llamada.
2. Invocar la rutina.
3. Éxito: guardar el resultado de la llamada al sistema en el contenido de los registros 0 y 1
salvado en la capa superior de la pila de capas de contexto del proceso. Desactivar el bit de
acarreo del registro 0 de estado del procesador salvado en la capa superior de la pila de capas
de contexto del proceso.
4. Error: guardar un identificador numérico del error (en errno, variable global) producido en el
contenido del registro 0 salvado en la capa superior de la pila de capas de contexto del
proceso. Activar el bit de accarreo en el contenido del registro 0 de estado del procesador
salvado en la capa superior de la pila de capas de contexto del proceso.

41
TRATAMIENTO DE ERROR ES EN LLAMADAS AL SISTEMA
De acuerdo con la interfaz de las llamadas al sistema descrito, si una llamada al sistema falla, la función
de librería asociada devolverá el valor -1.

Para averiguar cuál es el error que se ha producido, se ha de consultar el identificador numérico del
error almacenado en la variable global errno.

En el fichero de cabecera <errno.h> hay una descripción de todos los valores que puede tomar errno.
Algunos tienen asociada una constante, ej.: EINTR, llamada interrumpida por recepción de señal.

En la variable global sys_errlist definida en <stdio.h> se almacena una tabla con las cadenas
descriptoras de todos los códigos de error del sistema. Número de elementos que contiene: sys_nerr.

Tres formas de mostrar el mensaje de error de errno:

1. sys_errlist[errno]
2. char *strerror(errno). E imprimir con printf.
a. printf(“\n%d: %s\n”,errno,strerror(errno));
3. Función perror(cadena); Resultado: cadena:mensaje errno.

Cada llamada al sistema dispone de una página en el manual de ayuda de UNIX.

42
ESTADOS DE UN PROCESO

CONSIDERACIONES GENE RALES

Estados: (UNIX SVR2 o SVR3)

1. Ejecutándose en modo usuario. Ejecuta la región de código del proceso.


2. Ejecutándose en modo núcleo o supervisor.
3. Preparado en memoria principal para ser ejecutado.
4. Dormido o bloqueado en memoria principal.
5. Preparado en memoria secundaria para ser ejecutado.
6. Dormido o bloqueado en memoria secundaria.
7. Creado. Estado inicial para todos los procesos excepto PID=0.
8. Zombi. Ejecución explícita o implícita de exit.

Cuando a un proceso se le agota su cuanto, el reloj del sistema mandará una interrupción al procesador
que provoca que pase a modo núcleo y se decida si se expropia o no de acuerdo al planificador.

ESTADOS ADICIONALES

En BSD4 y soportados por SVR4.

 Estado parado o suspendido en memoria principal y secundaria. Ejecución detenida por acción
de una señal que posteriormente puede retomarse.
 Estado dormido y parado.

EL ESTADO DORMIDO

Un proceso pasa de ejecución en modo supervisor  dormido en memoria principal cuando:

43
 Durante la ejecución de una llamada al sistema el núcleo requiere un recurso ocupado o
esperar a E/S.
 Se produce un fallo de página.

Un proceso permanecerá en el estado dormido hasta que tenga lugar el evento por el que se encuentra
esperando. Cuando dicho evento ocurra, el proceso será despertado y pasará al estado preparado para
ejecución en memoria (principal o secundaria).

CANALES O DIRECCIONE S DE DORMIR


Para gestionar varios procesos que esperan por el mismo evento y los distintos eventos que genera cada
recurso, el núcleo clasifica los eventos en canales o direcciones de dormir.

Un canal es una dirección virtual del núcleo asociada a un determinado recurso. Distintos eventos
pueden estar asociados a un mismo canal.

LISTA DE PROCESOS DO RMIDOS


Un proceso pasa al estado dormido  el núcleo lo añade a la lista de procesos dormidos y almacena la
dirección de dormir en la entrada del proceso de la tabla de procesos.

ANOMALÍAS DE IMPLEME NTACIÓN DEL ESTADO D ORMIDO


Dos anomalías de esta implementación del estado dormido:

1. El núcleo despierta a todos los dormidos que esperan al mismo evento y sólo uno podrá ser
ejecutado.
2. Distintos eventos pueden asociarse a un mismo canal o dirección de dormir, aunque en la
práctica es raro que se asocien muchos eventos a un mismo canal.

INTERRUPCIÓN DE SEÑALES EN ESTADO DORMIDO


Una señal es un mecanismo de comunicación que utiliza el núcleo para informar a un proceso de la
ocurrencia de algún evento asíncrono.

Dos tipos de estado dormido:

 Estado dormido no interrumpible por señales. Algunas señales no pueden ser ignoradas. Es
para eventos que no tardarán mucho en producirse.
 Estado dormido interrumpible por señales. Es para eventos que pueden tardar en producirse,
como que el usuario pulse una tecla del teclado.

El núcleo determina si un proceso entra en dormido interrumpible o no interrumpible dependiendo


del valor de la prioridad de planificación de un proceso en modo núcleo, que depende del evento por
el que el proceso espera. Se suele denominar priridad para dormir.

Si prioridad de dormir > valor límite o umbral  proceso a estado dormido interrumpible.

Si no  proceso a estado dormido no interrumpible.

RESUMEN TEMA 3

1. Cuando se compila un programa, el compilador genera un espacio o conjunto de direcciones de


memoria virtual asociadas a dicho programa. La máquina traduce este espacio en un conjunto de
44
direcciones de memoria principal. Varias copias de un mismo programa pueden coexistir en memoria
principal, que utilizarán las mismas direcciones virtuales, pero con diferentes direcciones físicas
asignadas.

Un proceso es una instancia de un programa en ejecución. Al compilar el código fuente de un programa


se crea un archivo ejecutable que consta básicamente de cuatro partes: cabecera primaria (número
mágico, número de secciones, dirección virtual de inicio), cabecera de las secciones, secciones, y otras
informaciones.

El núcleo carga un fichero ejecutable en memoria principal durante, por ejemplo, la llamada al sistema
exec. El proceso cargado tiene asignado por el compilador un espacio de direcciones de memoria virtual
(o espacio de direcciones de usuario). Este espacio se divide en varias regiones. El espacio de direcciones
de memoria virtual de un proceso consiste al menos de tres regiones: la región de código (o texto), la
región de datos y la región de pila. Adicionalmente, puede contener regiones de memoria compartida,
que posibilitan la comunicación de un proceso con otros procesos.

Las principales operaciones con regiones implementadas por el núcleo son: bloquear y desbloquear una
región, asignar una región, ligar una región al espacio de direcciones virtuales de un proceso, cambiar el
tamaño de una región, cargar una región con el contenido de un fichero, desligar una región del espacio
de direcciones de un proceso, liberar una región y duplicar una región.

2. Dado que UNIX es multitarea, necesita identificar cada proceso. La forma de identificación consiste en
un número entero positivo distinto denominado identificador del proceso o pid

Cuando el sistema operativo arranca crea un proceso especial denominado proceso 0 al que asigna un
pid=0. Poco después el proceso 0 genera un proceso hijo denominado proceso inicial cuyo pid=1 y se
convierte en el proceso intercambiador (swapper). La llamada al sistema getpid devuelve el pid del
proceso que realiza esta llamada.

Dado que UNIX es multiusuario, el núcleo asocia a cada proceso dos identificadores enteros positivos de
usuario (identificador de usuario real (uid) y el identificador de usuario efectivo (euid)) y dos
identificadores enteros positivos de grupo (identificador del grupo real (gid) y el identificador del grupo
efectivo (egid)).

El núcleo mantiene diferentes estructuras de datos asociadas a los procesos. Algunas de estas
estructuras como la pila del núcleo, el área U y la tabla de regiones por proceso son locales a cada
proceso (cada proceso tiene asignada su propia estructura privada). Otras estructuras, como la tabla de
procesos y la tabla de regiones son globales para todos los procesos, es decir, sólo existe en el núcleo
una estructura para todos los procesos. La tabla de regiones por proceso contiene información relevante
sobre las regiones de código, datos, pila de usuario y memoria compartida (si existe) de un cierto
proceso. Cada entrada de esta tabla contiene un puntero que apunta a una entrada de la tabla de
regiones, con información sobre cada región. Las entradas de la tabla de regiones se organizan en dos
listas: una lista enlazada de regiones libres y una lista enlazada de regiones activas. Otras estructuras
son las tablas de páginas y la tabla de descriptores de ficheros.

3. El contexto de un proceso en un cierto instante de tiempo se puede definir como la información


relativa al proceso que el núcleo debe conocer para poder iniciar o continuar su ejecución.

El contexto de un proceso en un cierto instante de tiempo está formado por su espacio de direcciones
virtuales, los contenidos de los registros hardware de la máquina y las estructuras de datos del núcleo
asociadas a dicho proceso. Formalmente, el contexto de un proceso se puede considerar como la unión
del contexto a nivel de usuario, contexto de registros y contexto a nivel del sistema.

45
Durante el tiempo de vida de un proceso pueden producirse distintos sucesos: llamadas al sistema,
interrupciones, cambios de contexto... En el contexto de un proceso se distinguen una parte dinámica
(capa de contexto), cuyo contenido es necesario salvar ante la aparición de ciertos sucesos, y una parte
estática, cuyo contenido no es necesario salvar. La parte dinámica de un proceso está formada por el
contexto a nivel de registros y su pila del núcleo. La manipulación que el núcleo realiza de las capas de
contexto se puede visualizar como una pila de capas de contexto, local a cada proceso.

Se entiende por salvar el contexto de un proceso a la acción del núcleo de añadir una capa de contexto
en la pila de capas de contexto asociada a dicho proceso; y restaurar el contexto de un proceso es la
acción del núcleo de extraer la capa superior de la pila de capas de contexto asociada a dicho proceso e
inicializar el contexto de registros y la pila del núcleo con los valores que se habían salvado en dicha
capa. Se define el cambio de contexto como el conjunto de tareas que debe realizar el núcleo para
aplazar o finalizar la ejecución del proceso (A) actualmente en ejecución, y comenzar o continuar con la
ejecución de otro proceso (B).

4. Las interrupciones (hardware o software) son atendidas en modo núcleo dentro del contexto del
proceso que se encuentra actualmente en ejecución.

Cuando se produce una interrupción, el núcleo invoca al algoritmo inthand(), que realiza principalmente
las siguientes acciones: Salvar el contexto del proceso actual; elevar el nivel de prioridad de
interrupción, obtener el vector de interrupción, invocar al manipulador, restaurar el contexto del
proceso.

5. Las llamadas al sistema son el mecanismo que los procesos de usuario utilizan para solicitar al núcleo
el uso de los recursos del sistema. Un proceso invoca a una llamada al sistema como si se tratase de una
función de librería cualquiera, que entre otras, ejecutan una instrucción que provoca una interrupción
software especial denominada trap del sistema operativo. El tratamiento del trap por parte del núcleo
provoca el cambio de modo de ejecución a modo núcleo, salvar el contexto del proceso actual y la
invocación del algoritmo del núcleo que trata las llamadas al sistema, típicamente denominado syscall().

6. El tiempo de vida de un proceso en un sistema UNIX puede ser conceptualmente dividido en un


conjunto de estados que describen el comportamiento del proceso. Los ocho estados en que se puede
encontrar un proceso en un sistema UNIX (SVR2 o SVR3) son: ejecutándose en modo usuario,
ejecutándose en modo núcleo (o supervisor), preparado en memoria principal para ser ejecutado,
dormido o bloqueado en memoria principal, preparado en memoria secundaria para ser ejecutado,
dormido o bloqueado en memoria secundaria, creado y zombi.

EJERCICIOS TEMA 3

46
TEMA 4: ALGORITMOS DE CONTROL
DE PROCESOS EN UNIX
CREACIÓN DE PROCESOS

Creación de procesos  llamada al sistema fork().

 El único proceso no creado mediante fork es el proceso 0, que es creado internamente por el
núcleo cuando arranca el sistema.
 El proceso que invoca fork es el padre, el nuevo proceso es el hijo. Todos los procesos tienen
un padre excepto pid=0.
 La implementación de fork varía dependiendo de la política de gestión de memoria principal:
paginación por demanda o intercambio.

47
PROCESO DE CREACIÓN DEL HIJO
1. Invocación a la llamada al sistema fork.
2. El núcleo ejecutará syscall(), busca e invoca la rutina fork.
3. Ejecución de la rutina fork (intercambio):
a. Comprobación:
i. Suficiente memoria principal o secundaria para almacenar el proceso. [O
poder asignar memoria para alojar nuevas páginas].
ii. El usuario que invoca fork no tiene demasiados procesos ejecutándose.
Límite configurable, depende del tamaño límite de la tabla de procesos.
iii. En caso de no superar las comprobaciones  error durante la llamada al
sistema. Syscall() devuelve -1 y guarda el código de error en el registro 0 de la
capa superior de la pila de capas de contexto del padre.
b. Creación de la entrada del hijo en la tabla de procesos:
i. El núcleo asigna al hijo una entrada en la tabla de procesos y un pid.
ii. Configura el campo estado a creado.
iii. En la información genealógica copia el pid del proceso padre.
iv. Inicializa varios parámetros para la planificación del proceso, como
temporizadores y valores de prioridad.
v. Copia el contenido de la tabla de procesos del padre en el hijo.
1. Identificadores uid, euid, gid, egid  copia del padre.
2. Punteros a la tabla de regiones por proceso y al área U  copia del
padre.
3. Información asociada al tratamiento de las señales. ?
c. Incrementa el contador de referencias del nodo-i asociado al directorio de trabajo
actual del proceso padre, el hijo también residirá ahí.
d. Si sus antepasados utilizaron chroot para cambiar el directorio raíz, lo hereda y el
núcleo incrementa el contador de referencias de su nodo-i.
e. El núcleo busca en la tabla de archivos los ficheros abiertos por el padre e incrementa
el contador de referencias en sus entradas asociadas. Así el hijo comparte permisos de
acceso a los ficheros (por identificadores de usuario del padre) y los descriptores de
fichero.
f. Creación de la parte estática del contexto del hijo:
i. El núcleo copia en memoria la parte estática del contexto del padre (código,
datos, pila, área U, etc.) con el algoritmo dupreg() y la asocia con el hijo con
el algoritmo attachreg().
ii. Modifica el campo del área U con el puntero a la entrada de la tabla de
procesos para poner al hijo.
g. Creación de la parte dinámica del contexto del hijo:
i. Asigna memoria para la pila de capas de contexto del proceso hijo y añade
una copia de la capa 0 de la pila de capas de contexto del proceso padre.
ii. Si la pila del núcleo se implementa fuera del área U, asigna memoria para
ella. Será igual a la del padre.
iii. Añade otra capa de contexto, capa 1, en el hijo y configura el valor del
contexto de registros salvado en ella para que el proceso hijo pueda
comenzar a ejecutarse cuando sea planificado: guarda en el registro 0 un
valor que determine si se trata del proceso hijo o del padre y fija el contador
de programa a la dirección de la instrucción de la rutina fork donde debe
comenzar a ejecutarse el hijo (InstrC).
h. Cambio del hijo al estado preparado para ejecutarse en memoria principal.

48
4. Finaliza fork en el contexto del padre devolviendo a syscall() el pid del proceso hijo.
5. Finaliza fork en el contexto del hijo cuando sea planificado, syscall() le devuelve 0.

Finalizado el proceso, el padre y el hijo tienen idénticos:

 Contexto a nivel de usuario (código, datos, pila de usuario y memoria compartida).


 Tabla de descriptores de fichero, que al estar en el área U, se ha copiado igual. Por tanto, el
hijo comparte el acceso a los ficheros abiertos por el padre antes de fork.

SINTAXIS DE FORK
par = fork(); par es el pid del hijo para el padre y 0 para el hijo. Error, par=-1.

SEÑALES

GENERACIÓN Y TRATAMIENTO DE SEÑALES

Las señales notifican a los procesos eventos. Algunos eventos son notificaciones asíncronas y otros son
errores síncronos o excepciones. Tambien se pueden utilizar como mecanismo de comunicación y
sincronización de procesos.

Identificación mediante números enteros o constantes simbólicas. Varían dependiendo de la versión de


UNIX.

49
Mecanismo de señalización en dos fases:

 Generación  ocurre un evento que debe ser notificado y se genera una señal.
 Recepción o tratamiento  El proceso diana reconoce la llegada y toma las acciones
apropiadas.

Si una señal ha sido generada pero no ha sido tratada todavía está pendiente.

GENERACIÓN DE SEÑALE S
Principales fuentes de generación de señales:

 Excepciones.
 Otros procesos.
 Interrupciones del terminal.
 Control de tareas (intérpretes de comandos, procesos terminados o suspendidos se notifican al
padre).
 Cuotas (excede tiempo de uso de CPU o el tamaño máximo de un fichero).
 Notificaciones (operación E/S).
 Alarmas.

TRATAMIENTO DE SEÑALES
Cada señal tiene asignada una acción por defecto, existen cinco posibles:

 Abortar el proceso (genera fichero core con contexto usuario y registros para debug).

50
 Finalizar el proceso.
 Ignorar la señal.
 Parar o suspender el proceso. Si está dormido  dormido y parado
 Continuar el proceso.  estado preparado para ejecutar. Si dormido y parado  dormido.

Las acciones por defecto se evitan especificando otra acción alternativa:

 ignorar o,
 invocar al manejador de la señal definido por el usuario (señal capturada).

Las señales se procesan de una en una. Puede producirse anidamiento de manejadores.

Bloquear o enmascarar señales: la señal no será tratada hasta que sea desbloqueada. No se puede hacer
con todas las señales.

Cualquier acción que provoque la señal será realizada por el proceso que la reciba cuando vuelva a ser
ejecutado.

Los procesos reciben la señal cuando el núcleo invoca al algoritmo issig() para comprobar señales
pendientes, únicamente:

 Antes de volver al estado ejecución en modo usuario desde el estado ejecución en modo
supervisor, después de antender una llamada al sistema o una interrupción.
 Justo antesde entrar en el estado dormido interrumpible.
 Inmediatamente después de despertar del estado dormido interrumpible.

TRATAMIENTO DE SEÑALES:

1. Se invoca a issig():
a. Comprueba el campo p_sig en la entrada asociada al proceso en la tabla de procesos.
b. p_sig es una máscara de bits, si hay bits activados es que hay señales pendientes (al
menos una).
c. Desactiva el bit del campo correspondiente y devuelve VERDADERO.
d. El núcleo recibe VERDADERO de issig() y ejecuta psig() para tratar la señal.
e. Algoritmo psig():
i. Si no hay manejador, ejecuta la acción por defecto asociada a la señal.
ii. Si existe manejador, llama a sendsig().
iii. Algoritmo sendsig():
1. Busca la dirección del manejador en el campo u_signal del área U del
proceso (array con una entrada por cada señal con un valor
constante como SIG_DFL o SIG_IGN, o la dirección de inicio del
manejador).
2. Arreglos en la pila de capas de contexto asociada al proceso para que
éste pueda continuar su ejecución después del que el manejador
termine de ejecutarse:
a. El núcleo recupera el contador del programa y el registro de
pila de la capa 0.
b. Crea un nuevo marco de pila en la pila de usuario y escribe
los valores recogidos en el paso anterior.
c. Accede al contexto de registros salvado en la capa 0 de la
pila de capas de contexto y escribe en el contador del
programa la dirección del manejador de la señal.

51
La implementación de sendsig() es muy dependiente de máquina.

La llamada al manipulador es asíncrona.

Si la señal llega cuando se estaba en modo núcleo ejecutando una llamada al sistema, el núcleo
normalmente aborta la llamada al sistema con el algoritmo longjmp() y el proceso retorna a modo
usuario. El proceso ejecuta el manejador y luego recibe el error (-1) de la llamada al sistema, errno será
EINTR, llamada al sistema interrumpida por recepción de señal.

ESCENARIOS TÍPICOS
Interrupción o excepción  modo núcleo  núcleo invoca inthand()  inthand() envía señal al proceso
 antes de volver al estado en modo usuario, núcleo llama a issig()  retorna a modo usuario y recibe
la señal  manejador o acción por defecto  regresa a su código.

Las excepciones provocan señales asíncronas.

PROBLEMAS DE CONSISTENCIA EN EL MECANISMO DE SEÑALIZACIÓN

PLANTEAMIENTOS DE LOS PROBLEMAS


En distribuciones SVR2 y anteriores:

 Manejadores no persistentes, había que reinstalarlos después de la primera aparición de la


señal.
 No se puede saber de antemano si un proceso dormido va a ignorar una señal y hay que
despertarlo igualmente.

SOLUCIONES DE LOS PROBLEMAS DE CONSISTEN CIA


Las nuevas versiones de UNIX poseen un mecanismo de señalización consistente y fiable que solventó
los problemas:

 Manejadores persistentes, no es necesario reinstalarlos.


 Procesos dormidos  la información de control de señales está en la tabla de procesos
además de en el área U.
 Enmascarado temporal. El núcleo recuerda la señal y no la notifica hasta que el proceso la
desbloquee. Para proteger regiones de código críticas.

UN EJEMPLO DE MECAN ISMO DE SEÑALIZACIÓN CONSISTENTE


El implementado en la distribución SVR4.

Mantiene en el área U u_signal, vector que contiene la dirección de inicio del manejador asociado a
cada señal.

Información asociada a la notificación de señales en la tabla de procesos:

p_cursig – número señal actualmente tratada.

p_sig – máscara de señales pendientes.

p_hold – máscara de señales bloqueadas.

52
p_ignore – máscara de señales ignoradas.

El núcleo comprueba p_hold en los procesos dormidos interrumpibles antes de despertarlos en vano.

El algoritmo issig() comrpueba p_hold para comprobar si la señal está enmascarada.

LLAMADAS AL SISTEMA PARA EL MANEJO DE SEÑALES

LLAMADAS AL SISTEMA KILL


resultado = kill(par, señal);

par. Entero que identifica a los destinatarios:

 Si par>0  pid=par.
 Si par=0  todos los procesos del mismo grupo.
 Si par=-1  todos cuyo uid sea igual al euid del emisor. Si emisor tiene euid de superusuario,
envía a todos los procesos excepto pid=1.
 Si par<-1  todos cuyo gid sea igual al valor absoluto de par.

En terminal:

$ kill -señal pid

Si el proceso emisor no tiene euid root o privilegios sobre el proceso que va a recibir la señal, la llamada
al sistema kill falla.

Versión mejorada de kill en SVR4  sigsendset.

Por defecto envía señal SIGTERM.

Otros:

$ pkill -señal nombre_proceso

$ killall -señal nombre_proceso

LLAMADA AL SISTEMA RAISE


Permite a un proceso enviarse una señal a sí mismo.

resultado = raise(señal); Devuelve 0, bien, o -1 error.

LLAMADA AL SISTEMA SIGNAL


Especifica el tratamiento de una determinada señal recibida (manejador de la señal).

resultado = signal(señal, acción);

acción puede ser:

 Constante entera SIG_DFL.


 Constante entera SIG_IGN.
 Dirección del manejador de la señal definido por el usuario.

53
Devuelve la acción que tenía asignada dicha señal antes o error SIG_ERR=-1.

El comando equivalente del shell para atrapar una señal es trap.

LLAMADA AL SISTEMA P AUSE


El proceso que la invoca queda a la espera de recibir una señal que no ignore y que no tenga bloqueada.

resultado=pause(); Devuelve -1 en éxito y en errno se almacena EINTR.

Llamadas semejantes a pause pero de mayor versatilidad:

sigpause (BSD4.3) y sigsuspend (SVR4).

LLAMADAS AL SISTEMA PARA ENMASCARAR SEÑALES


La llamada sigsetmask fija la máscara actual de señales para el proceso.

resultado=sigsetmask(máscara); Devuelve máscara anterior o -1 en error.

Se puede fijar el bit j en la máscara con la macro sigmask(j).

Llamada sigblock para añadir nuevas señales bloqueadas a la máscara existente.

resultado=sigblock(máscara2); Devuelve máscara anterior o -1 en error.

máscara = máscara | máscara 2;

Otra llamada al sistema para el manejo de la máscara de señales es sigprocmask de SVR4.

En general estas llamadas al sistema han quedado obsoletas (aunque todavía pueden usarse en muchas
versiones de UNIX) y han sido reemplazadas por sus equivalentes POSIX.

DORMIR Y DESPERTAR A UN PROCESO

ALGORITMO SLEEP()

Pasar un proceso al estado dormido. Parámetros: prioridad para dormir y dirección de dormir o canal.

Algoritmo sleep():

1. Salva el nivel de prioridad de interrupción actual, en el registro del procesador.


2. Eleva el npi para bloquear todas las interrupciones.
3. Marca el proceso a dormido en memoria principal en la tabla de procesos, salva la prioridad
para dormir y la dirección de dormir.
4. Coloca al proceso en una lista de procesos dormidos.
5. Compara la prioridad para dormir con un valor umbral para establecer o no la interrupción por
señales.
a. Si el proceso no puede ser interrumpido por señales:
i. Cambio de contexto  sleep() es momentáneamente detenido.
ii. Si se genera una señal y aún no ha despertado el proceso se marca como
pendiente.
iii. Cuando sea despertado y planificado continuará con la siguiente instrucción
de sleep()  restaurar el valor npi al inicial y finaliza.
b. Si el proceso puede ser interrumpido por señales:

54
i. Invoca a issig():
1. Si hay señales pendientes:
a. Borra al proceso de la lista de dormidos.
b. Restaura el npi.
c. Invoca a psig().
2. Si no hay señales pendientes:
a. Cambio de contexto  sleep() es momentáneamente
detenido.
b. Despierta por un evento por el que esperaba o recibe una
señal, y es planificado.
c. Invoca al algoritmo issig():
i. Si no hay señales pendientes:
1. Restaura el npi.
2. Finaliza.
ii. Si hay señales pendientes:
1. Restaura el npi.
2. Sleep() invoca a psig().

El algoritmo sleep() no requiere ejecutarse hasta el final para lograr su objetivo de pasar a un proceso al
estado dormido.

La pila de capas de contexto de un proceso dormido contiene dos capas:

 La capa 1 con información para continuar con sleep().


 La capa 0 con información para retomar la ejecución del proceso en modo usuario.

55
ALGORITMO WAKEUP()

Despierta a un proceso dormido a la espera de un evento. La invocación se realiza típicamente detro de


otros algoritmos del núcleo. Parámetro: la dirección de dormir o canal asociada al evento.

Agoritmo wakeup():

1. Salva el npi actual.


2. Eleva el npi para bloquear todas las interrupciones.
3. Busca en la lista de procesos dormidos aquellos que esperan por el evento de la dirección de
dormir.
4. Para cada uno de los que encuentre:
a. Elimina al proceso de la lista de procesos dormidos.
b. Marca estado a preparado para ejecución en memoria principal o secundaria.
c. Coloca al proceso en la lista de procesos elegibles para ser planificados.
d. Borra el contenido del campo dirección de dormir o canal.
e. Despierta al proceso intercambiador en caso de estar el dormido en memoria
secundaria.
f. Si ya está en memoria principal y este proceso es más prioritario que el actual, activa
el indicador runrun en su entrada de la tabla de procesos.
5. Restaura el npi.
6. Finaliza wakeup().

56
TERMINACIÓN DE PROCESOS

En un sistema UNIX un proceso finaliza cuando se ejecuta la llamada al sistema exit.

El proceso pasa a estado zombi y se elimina todo su contexto excepto su entrada en la tabla de
procesos. El núcleo siempre ejecuta el algoritmo exit() para terminar un proceso:

 Invocación explícita: exit();


 Invocación implícita: fin de main.

Sintaxis de la llamada a exit:

exit(condición);

 Donde condicion es el código de retorno para el proceso padre.


 No genera parámetros de salida.

Algoritmo exit():

1. Primero deshabilita el tratamiento de señales para el proceso.


2. Recorre la tabla de descriptores de ficheros del proceso para ir cerrando los ficheros abiertos.
3. Libera el nodo-i del directorio de trabajo actual y el raíz si hubiese cambiado.
4. Libera la memoria principal con detachreg() y freereg().
5. Cambia al estado zombie.
6. Salva el código de retorno para el proceso padre e información estadística.
7. Escribe en un fichero de contabilidad global la información estadística (uid, uso CPU, memoria,
rescursos, etc) para monitorización.
8. Desconecta el proceso del árbol de procesos y el proceso inicial adopta a sus hijos, que se
convierten en demonios.
9. Envía señal SIGCHLD al padre. Siempre al borrar procesos.
10. Los hijos zombie del proceso son borrados por el proceso inicial al recibir señal SIGCHLD.
11. Finaliza el algoritmo y hay un cambio de contexto según planificación.

57
ESPERAR LA TERMINACIÓN DE UN PROCESO

Un proceso puede esperar a la terminación de un proceso hijo con wait.

resultado = wait(direc); Devuelve pid del hijo terminado o -1 en error.

El parámetro direc es la dirección del código de retorno para el proceso padre generado por el algoritmo
exit() al terminar el hijo.

Algoritmo wait():

1. Comprueba que el proceso tiene algún hijo.


a. Si no hay hijos finaliza y devuelve error.
b. Si hay hijos entra en bucle comprobando la existencia de hijos zombies.
i. Si hay un hijo zombie escoge al primero que encuentra.
1. Extrae la entrada de la tabla de procesos, su pid y su código de
retorno para el padre.
2. Añade en el área U el tiempo en modo usuario y modo núcleo del
hijo.
3. Borra la entrada de la tabla de procesos del hijo.
4. Finaliza devolviendo al padre el pid del proceso hijo y el código de
retorno.
ii. Si no hay hijos zombie, invoca sleep() y el padre pasa a dormido
interrumpible.
iii. Como al terminar un proceso se envía la señal SIGCHLD al padre, el padre
será despertando y, aunque no tiene manejador de señal, ya encontrará un
hijo zombie cuando reanude su ejecución y pase de:
sleep()  issig()  psig()  wait().

INVOCACIÓN DE OTROS PROGRAMAS

FUNCIONES DE LIBRERÍ A

La llamada al sistema exec sirve para invocar desde un proceso a otro programa ejecutable (compilado
o shell script). Éste cargará las regiones de código, datos y pila del nuevo programa en el contexto de
usuario del proceso que invoca a exec. Por tanto, ya no se podrá acceder a las regiones de usuario del
proceso invocador porque habrán sido sustituidas.

Familia de funciones de librería exec:

 resultado=execl(ruta, arg0, arg1,..., argN, NULL);


 resultado=execv(ruta, argv);
 resultado=execle(ruta, arg0, arg1,..., argN, NULL, envp);
 resultado=execve(ruta, argv, envp);
 resultado=execlp(fichero, arg0, arg1,..., argN, NULL);
 resultado=execvp(fichero, argv);

Donde ruta es la ruta del fichero, fichero es el nombre del fichero y su ruta se busca en PATH, arg
son punteros a cadenas de caracteres. Por convenio, arg0 siempre está y es el nombre del ejecutable
(ruta). Para indicar el final de los argumentos, siempre se pone NULL al final.

58
Se puede pasar el entorno con envp, un array de punteros a cadenas de caracteres terminado en un
puntero nulo. Cada cadena es una variable de entorno con la forma
VARIABLE_ENTORNO=VALOR_VARIABE. Para obtener o declarar variables se usan getenv y putenv,
definidas en <stdlib.h>. Si no pasamos entorno, éste será accesible a través de la variable global
environ de la librería C. El entorno de un proceso es heredado por todos sus procesos hijos.

Si el programa invocado es compilado, tiene un número mágico en su cabecera primaria que lo


identifica como directamente ejecutable recibe argumentos y entorno en el main:

main(int argc, char *argv[], char *envp[]);

Si no tiene número mágico es considerado un shell script y se le pasa al intérprete de comandos.

Si falla la llamada exec se devuelve el control al proceso que lo invoca, devuelve -1 y el código de error
se almacena en errno.

EL ALGORITMO EXEC()

Parámetros de entrada:

 La ruta.
 La lista de argumentos o parámetros.
 Las variales de entorno del fichero ejecutable.

Algoritmo exec():

1. Encuentra el nodo-i del archivo con ruta.


2. Verifica los permisos para ejecutar el fichero del proceso invocador.
3. Lee la cabecera del fichero ejecutable para comprobar que es un ejecutable válido.
4. Con S_ISUID o S_ISGID activados, cambia el euid y el egid del proceso invocador para que sea
igual al uid o gid del propietario del fichero.
5. Salva en un área de memoria del núcleo los parámetros de entrada de la función exec que
estaban en la región de datos del proceso invocador, porque éste será destruido.
6. Desliga el contexto de usuario del invocador con detachreg().  error causa terminación del
proceso por no tener dónde volver.
7. Asigna y liga al proceso las nuevas regiones de código y datos con allocreg() y attachreg().
8. Carga en dichas regiones el código del ejecutable con loadreg().
9. Primero carga los datos inicializados y luego emplea growreg() para tener espacio para los no
inicializados.
10. Asigna y liga una región para la pila del proceso y copia los parámetros de entrada de la
llamada a exec que había guardado.
11. Terminada la configuración del nuevo contexto de usuario.
12. Borra del área U las direcciones de los manejadores de señales y lo deja todo por defecto.
13. Las señales que eran ignoradas o bloqueadas antes de invocar a exec permanecerán así en el
nuevo.
14. Modifica el contexto de registros salvado en la capa 0 para que el programa comience, carga el
contador del programa con la dirección de inicio del nuevo programa.

59
HEBRAS

MOTIVACIÓN

 Mejorar el rendimiento de multiprocesador.


 Aplicaciones inherentemente paralelas por naturaleza.

La abstracción hebra representa a una unidad computacional que es parte de un trabajo de


procesamiento de una aplicación, e interaccionan entre sí muy poco.

Un proceso se puede dividir en:

 Un conjunto de hebras. La hebra es un objeto dinámico que representa un punto de control en


el proceso y ejecuta una secuencia de instrucciones. Las hebras tienen un contador de
programa, una pila y un contador de registro privados.
 Una colección de recursos. Son compartidos por todas las hebras de un proceso.

TRES TIPOS:

HEBRAS DEL NÚCLEO

 No necesita ser asociada con un proceso de usuario.


 Creada y destruida internamente por el núcleo.
 Comparte el código del núcleo y sus estructuras globales.

60
 Planificada independientemente.
 Puede utilizar mecanismos de sincronización estándar del núcleo.
 Necesitan pila del núcleo y contexto a nivel de registro.

Ventajas:

 Económicas de crear y usar.


 Cambio de contexto rápido.
 El ladrón de páginas es funcionalmente equivalente a las hebras del núcleo.

PROCESOS LIGEROS

Un proceso ligero es una hebra de usuario soportada por el núcleo.

 Cada proceso puede tener uno o más procesos ligeros.


 Son planificados independientemente.
 Comparten espacio de direcciones y recursos del proceso.
 Pueden hacer llamadas al sistema y bloquearse en espera de algún recurso.
 Cada proceso ligero puede encaminarse a un procesador diferente en sistemas
multiprocesador.
 También hay ventajas en cuanto a esperas por recursos en sistemas monoprocesador.
 Necesita mantener pila del núcleo, contexto a nivel de registro y contexto a nivel de usuario.
 Necesitan a las hebras del núcleo mientras que éstas no los necesitan a ellos.
 Los procesos multihebras son muy útiles cuando cada hebra es bastante independiente y no
interactúa con otras hebras.
 El código del usuario es completamente expropiable.

Limitaciones:

 Sobrecarga del sistema por llamadas al sistema y cambios de contexto.


 Sobrecarga por la sincronización.
 Consumen recursos del núcleo de forma significativa.
 El sistema tiene una única implementación de proceso ligero que debe adaptarse a todas las
aplicaciones más comunes.

61
HEBRAS DE USUARIO

Se transfiere la abstracción de la hebra a nivel de usuario, sin intervención del núcleo.

 Paquetes de librería como C-threats de Mach o pthreads de POSIX.


 Suministran todas las funciones para crear, sincronizar, planificar y gestionar hebras sin
asistencia del núcleo.
 El núcleo conmuta entre procesos, pero no sabe de la existencia de las hebras.

Ventajas:

 Suministran una forma natural de programar muchas aplicaciones.


 Paradigma de programación síncrona.
 Librerías de hebras optimizadas para el tipo de aplicación.
 Son computacionalmente ligeras y no consumen recursos del núcleo.
 Implementan la funcionalidad a nivel de usuario sin llamadas al sistema.
 Tamaño crítico de una hebra.
 Requieren menos tiempo para todo que los procesos ligeros o los procesos.

Limitaciones:

 No hay intercambio de información para la planificación de hebras y procesos.


 Mejoran la concurrencia pero no el paralelismo.

Cuando una función de librería puede usar hebras se dice que es “thread safe” y es importante
asegurarse de que la librería que se esté usando funcione bien con hebras.

RESUMEN TEMA 4

1. En un sistema UNIX la única forma que tiene un usuario de crear un nuevo proceso es invocando a la
llamada al sistema fork.

62
Al proceso que invoca a fork se le denomina proceso padre, y el proceso hijo es el nuevo proceso que se
crea. En la primera parte de este capítulo se describe las principales acciones que realiza el núcleo
durante la ejecución de la rutina asociada a la llamada al sistema fork, mediante la ejecución del
algoritmo syscall(). Estas acciones comprender la comprobación de la existencia de recursos suficientes
(memoria), y de que no existen demasiados procesos ejecutándose. Si la comprobación es positiva, el
núcleo asigna al nuevo proceso hijo una entrada en la tabla de procesos y un pid, y crea el contexto del
proceso hijo a partir de una copia del contexto del proceso padre. A continuación, el núcleo cambia el
estado del proceso hijo al estado preparado para ejecutarse en memoria principal. Cuando el proceso
hijo sea planificado para ser ejecutado, su contexto será restaurado, es decir, el núcleo extraerá la capa
1 de la pila de capas de contexto. Finalmente, la ejecución finaliza en el contexto del hijo devolviendo a
syscall() el valor 0.

2. Las señales proporcionan un mecanismo para notificar a los procesos los eventos que se producen en
el sistema. Los eventos se identifican mediante números enteros. Algunos de estos eventos son
notificaciones asíncronas, son errores síncronos o excepciones. También se pueden utilizar como un
mecanismo de comunicación y sincronización entre procesos.

En el mecanismo de señalización se distinguen dos fases principalmente: generación y tratamiento. Una


señal es generada cuando ocurre un evento (causado por el propio proceso receptor, otro proceso,
interrupciones o acciones externas) que debe ser notificado a un proceso. La señal es recibida o tratada,
cuando el proceso para el cual fue enviada la señal reconoce su llegada y toma las acciones apropiadas.
Cada señal tiene asignada una acción por defecto, que realizará el núcleo si el proceso no ha
especificado una, y son: abortar, finalizar, suspender, continuar el proceso e ignorar la señal. En el caso
de especificar una acción alternativa, esta puede ser ignorar la señal o invocar a una función definida
por el usuario (manejador de la señal). El proceso receptor se da cuenta de la existencia de la señal
cuando el núcleo (en el nombre del proceso) invoca al algoritmo issig() para comprobar la existencia de
señales pendientes.

En esta parte del capítulo se describen varias llamadas al sistema para el manejo de señales, como son:
kill, raise, signal, pause, sigsetmask, sigblock.

3. Para pasar un proceso al estado dormido, el núcleo usa el algoritmo sleep (). Este algoritmo requiere
como parámetros de entrada la prioridad para dormir y la dirección de dormir o canal asociada al
evento por el que estará esperando el proceso.

Las acciones que realiza sleep() se pueden resumir en las siguientes: elevar el npi para bloquear las
interrupciones, marcar en la tabla de procesos que el estado es dormido; guardar en la tabla de
procesos la dirección de dormir y la prioridad para dormir, y colocar al proceso en la lista de procesos
dormidos. A continuación compara la prioridad para dormir con un cierto umbral, para comprobar si
puede ser interrumpido. En caso afirmativo, se distinguen el caso en que el proceso puede o no ser
interrumpido por señales. Si puede ser interrumpido, el núcleo invoca al algoritmo issig() para
comprobar la existencia de señales pendientes, en cuyo caso el núcleo borra el proceso de la lista de
procesos dormidos, restaura el valor del npi e invoca al algoritmo psig(). En caso contrario, el núcleo
realiza un cambio de contexto, y la ejecución es momentáneamente detenida. Cuando el proceso se ha
despertado, se invoca de nuevo al algoritmo issig().

Para despertar a un proceso que se encuentra en el estado dormido a la espera de la aparición de un


determinado evento, el núcleo usa el algoritmo wakeup(). La invocación de este algoritmo se realiza
dentro de algún otro algoritmo, como los asociados a las llamadas al sistema, o a las rutinas de
manipulación de interrupciones, o cuando genera una señal para un proceso. Las acciones que realiza el
núcleo son las siguientes: elevar el npi para bloquear las interrupciones, buscar en la lista de procesos

63
dormidos a aquellos procesos que están a la espera de la aparición del evento asociado a la dirección de
dormir, que implica eliminar al proceso de la lista, y a continuación marcar en el campo estado de su
estado de la tabla de procesos el estado de preparado para su ejecución. Si el proceso despertado no
estaba cargado en memoria principal, el núcleo despierta al proceso intercambiador. En caso contrario,
si el proceso es más elegible para ser ejecutado, el núcleo activa un indicador denominado runrun.
Cuando ya no quedan más procesos en la lista, el núcleo restaura el npi y el algoritmo finaliza.

4. Un proceso finaliza cuando se ejecuta la llamada al sistema exit. El algoritmo exit() requiere como
parámetro de entrada el código de retorno para el proceso padre. Las acciones que realiza el núcleo
durante la ejecución de este algoritmo son resumidamente: deshabilitar el tratamiento de las señales;
cerrar todos los ficheros abiertos por el proceso, liberar recursos (nodos-i, memoria), marcar el estado
del proceso a zombi en su entrada de la tabla de procesos, salvar datos estadísticos y el código de
retorno en su entrada de la tabla de procesos, y hacer que el proceso inicial adopte a los procesos hijos
del proceso si existen. Si la respuesta afirmativa, se envía una señal SIGCHLD al proceso inicial para que
borre sus entradas de la tabla de procesos. Finalmente, el núcleo hace un cambio de contexto.

5. Finalmente, el algoritmo esperar la terminación de un proceso (wait) permite sincronizar la ejecución


de un proceso con la terminación de algunos de sus procesos hijos. Las principales acciones que realiza
es: comprobar que el proceso posee algún hijo; en cuyo caso el núcleo comprueba si alguno está en
estado zombi. Si existe alguno, busca un hijo en este estado zombi, borra los contenidos de la entrada
asociado en la tabla de procesos, y devuelve el pid del hijo y el código de retorno. Si no existe ningún
proceso hijo en estado zombi, el núcleo invoca al algoritmo sleep().

La llamada al sistema exec sirve para invocar desde un proceso a otro programa ejecutable (programa
compilado o shell script). Básicamente exec carga las regiones de código, datos y pila del nuevo
programa en el contexto de usuario del proceso que invoca a exec. Una vez concluida esta llamada al
sistema, ya no se podrá acceder a las regiones de código, datos y pila del proceso invocador. Existe toda
una familia de funciones de librería asociadas a esta llamada al sistema: execl, execv, execle, execve,
execlp y execvp.

Al tratar la llamada al sistema exec desde alguna de sus funciones de librería, el núcleo invoca a la rutina
o algoritmo exec(). Las acciones que se realizan son: localizar el nodo-i del fichero, comprobar que el
usuario tiene permiso para ejecutarlo y de que se trata de un fichero ejecutable, salvar en un área del
núcleo los parámetros de entrada de la función de biblioteca asociada a exec, desligar del proceso sus
regiones de código, datos y pila de usuario, configurar un nuevo contexto de usuario, copiar en la pila
los parámetros de entrada de la función exit, y configurar el contexto de registros salvado en la capa 0
de la pila de capas de contexto para poder comenzar la ejecución del fichero ejecutable.

6. Con el modelo de proceso, existen deficiencias tales como la necesidad de disponer de mejores
servicios para el procesamiento paralelo. Las distribuciones de UNIX modernas resuelven las
limitaciones que aparecen con el modelo de proceso proporcionando el modelo de hebra (thread). La
abstracción hebra representa a una unidad computacional que es parte de un trabajo de procesamiento
de una aplicación. De forma general un proceso se puede considerar como una entidad compuesta que
puede ser dividida en dos componentes: un conjunto de hebras y una colección de recursos. La hebra es
un objeto dinámico que representa un punto de control en el proceso y que ejecuta una secuencia de
instrucciones. Los recursos (espacio de direcciones, ficheros abiertos, credenciales de usuario, cuotas,...)
son compartidos por todas las hebras de un proceso. En función de sus propiedades y usos se distinguen
tres tipos diferentes de hebras: hebras del núcleo, procesos ligeros y hebras de usuario.

EJERCICIOS TEMA 4

64
65
TEMA 5: PLANIFICACIÓN DE PROCESOS
EN UNIX
INTRODUCCIÓN

TRATAMIENTO DE LAS INTERRUPCIONES DEL RELOJ

CONSIDERACIONES GENE RALES

CALLOUTS

ALARMAS

LLAMADAS AL SISTEMA ASOCIADAS CON EL TIEMPO

FIJACIÓN DE LA FECHA DEL SISTEMA


resultado=stime(&valor);

LECTURA DE LA FECHA DEL SISTEMA


fecha=time(&valor);

TIEMPOS DE EJECUCIÓN ASOCIADOS A UN PROCESO


resultado=times(&tbuffer);

PLANIFICACIÓN TRADICIONAL EN UNIX

PRIORIDADES DE PLANI FICACIÓN DE UN PROCE SO


IMPLEMENTACIÓN DEL PLANIFICADOR
MANIPULACIÓN DE LAS COLAS DE EJECUCIÓN
ANÁLISIS

PLANIFICADOR DEL SVR4

LA CAPA DEPENDIENTE DE LA CLASE


INTERFAZ PARA LAS CL ASES DE PLANIFICACIÓN
LA CLASE DE TIEMPO COMPARTIDO

66
LA CLASE DE TIEMPO REAL
ANÁLISIS

PLANIFICADOR DEL SOLARIS 2.X

RESUMEN TEMA 5

El planificador es el componente del sistema operativo que determina qué proceso debe ejecutarse en
cada instante, y cede el uso de la CPU a cada proceso durante un tiempo llamado cuanto antes de
planificar a otro proceso para su ejecución. En un sistema se ejecutará distintas aplicaciones de forma
concurrente, que se clasifican en interactivas, aplicaciones batch, y en tiempo real. Una descripción
adecuada del planificador debe centrarse en dos aspectos: la política de planificación y la
implementación. La política de planificación debe intentar cumplir: dar respuesta rápida, productividad,
garantizar límites para el tiempo, evitar el abandono de procesos, asegurar que las funciones del núcleo
se ejecuten.

2. Cada máquina UNIX tiene un reloj hardware que interrumpe al sistema a intervalos de tiempo. Se
denomina tic al periodo de tiempo entre dos interrupciones del reloj. El tratamiento de la interrupción
depende del sistema fuertemente, y debe realizar las siguientes tareas: rearmar el reloj, adaptar las
estadísticas de uso de la CPU, enviar una señal SIGXCPU, comprobación de los callouts, despertar a los
procesos del sistema, y comprobar alarmas.

Los callouts son un mecanismo interno del núcleo que le permite invocar funciones transcurrido un
cierto tiempo. Suele almacenar el nombre de la función a invocar, un argumento para dicha función y el
tiempo en tics transcurrido el cual la función debe ser invocada. Se suele emplear para la invocación de
tareas periódicas, como la transmisión de paquetes. Los usuarios no tienen ningún control sobre este
mecanismo. El núcleo mantiene una lista de callouts, que se puede implementar de varias formas.

El mecanismo de aviso en el que un proceso solicita al núcleo el envío de una señal una vez transcurrido
un determinado tiempo se conoce como alarma. Existen tres tipos: alarma de tiempo real, de tiempo
virtual, y de perfil. Una elevada resolución de una alarma de tiempo real no implica una alta resolución,
al contrario que ocurre con los otros dos tipos.

En este capítulo también se analizan algunas llamadas al sistema asociadas con el tiempo, como stime,
que permite fijar la fecha y hora actuales. La llamada al sistema time permite leer la fecha y la hora
actuales. La llamada al sistema times permite conocer el tiempo empleado por un proceso en su
ejecución.

Por otro lado, se estudia la planificación tradicional del planificador utilizado en BSD4.3, que es del tipo
round robin con colas multinivel con realimentación. El planificador siempre selecciona al proceso que
encontrándose en el estado preparado en memoria principal para ser ejecutado o en el estado
expropiado tiene la mayor prioridad. El planificador varía dinámicamente la prioridad de los procesos
basándose en su tiempo de uso de la CPU. Si un proceso de mayor prioridad alcanza el estado preparado
en memoria principal para ser ejecutado, el planificador expropia el uso de la CPU al proceso actual
incluso aunque éste no haya completado su cuanto. El núcleo tradicional de UNIX es estrictamente no
expropiable. La prioridad de planificación de un proceso es un valor entre 0 y 127. El núcleo asocia una
prioridad (en modo núcleo) de dormir en función del evento por el que el proceso entró en el estado
dormido. La prioridad en modo usuario depende de dos factores: el factor de amabilidad y el tiempo de
uso de la CPU. En el factor de amabilidad, cuando un usuario incrementa este valor, disminuye la

67
prioridad de sus procesos y le cede el turno de uso de CPU a otros usuarios. El factor de uso de la CPU
suministra justicia y paridad en la planificación de los procesos de tiempo compartido.

3. Por último, se analizan los planificadores del SVR4 y del Solaris 2.x.

Los principales objetivos del planificador del SVR4 son: soportar distintos tipos de aplicaciones, separar
la política de planificación de los mecanismos que la implementan, mayor control sobre prioridades y
planificación de las aplicaciones, definir un entorno de planificación con interfaz bien definida, permitir
nuevas políticas de planificación añadidas de forma modular, y limitar el retardo de encaminamiento.

La abstracción fundamental que introduce este planificador es la de clase de planificación, la cual define
la política de planificación para todos los procesos que pertenecen a ella. La capa independiente de la
clase es la responsable del cambio de contexto, gestión de las colas de ejecución y expropiación.

La clase de planificación decide las políticas para el cálculo de la prioridad y la planificación de los
procesos que pertenecen a dicha clase. También determina el rango de prioridades para sus procesos y
bajo que condiciones la prioridad del proceso puede cambiar; y el tamaño del cuanto de cada proceso.
La clase de tiempo compartido es la clase por defecto para un proceso, y utiliza planificación conducida
por eventos. La clase de tiempo real utiliza prioridades en el rango 100-159, lo que significa que un
proceso de tiempo real será planificado antes que cualquier proceso del núcleo.

4. Solaris 2.x mejoró la arquitectura de planificación básica del SVR4 en varios aspectos. Solaris es un
sistema multihebra, y multiprocesador simétrico. Adicionalmente, Solaris utiliza varios mecanismos de
optimización del retardo de distribución de los procesos de alta prioridad que deben ejecutarse en un
tiempo límite. El resultado es un planificador que es más adecuado para procesamiento en tiempo real.
El núcleo de Solaris 2.x es completamente expropiable, lo cual permite garantizar buenos tiempos de
respuesta.

EJERCICIOS TEMA 5

68
TEMA 6: COMUNICACIÓN Y
SINCRONIZACIÓN DE PROCESOS EN
UNIX
INTRODUCCIÓN

SERVICIOS IPC UNIVERSALES

SEÑALES

Notificación a un proceso de eventos asíncronos.

Limitaciones:

 Costosas.
 Ancho de banda limitado: 32 tipos de señales.
 Transportan cantidad limitada de información.

TUBERÍAS

Mecanismo de comunicación unidireccional para transmisión de un flujo de datos no estructurados.

TUBERÍAS SIN NOMBRE


resultado=pipe(tubería);

Limitaciones:

 No transmite a múltiples receptores simultáneamente. Los datos leídos son borrados.


 No se pueden dirigir los datos a un proceso concreto si hay más de uno.
 No se pueden determinar cuántos mensajes o dónde empieza o termina cada uno. Es un flujo
continuo de bytes no estructurados de tamaño fijo.

Pueden implementarse como ficheros, sockets o streams (full-duplex).

TUBERIAS CON NOMBRE O FICHEROS FIFO


resultado= mknod(ruta, modo, 0);

Ventajas sobre tuberías sin nombre:

 Tienen nombre.
 Pueden ser accedidos por otros procesos sin relación familiar.
 Son persistentes.

Desventajas:

 Deben ser borrados.


69
 Son menos seguros.
 Son difíciles de configurar y consumen más recursos.

LECTURA Y ESCRITURA EN LAS TUBERÍAS (SIN NOMBRE Y FICHEROS FIFO)


Se utilizan las llamadas al sistema read y write sobre los descriptores de la tubería.

MECANISMOS IPC DEL SYSTEM V

CONSIDERACIONES GENE RALES

Nomenclatura:

 Mecanismo IPC: formas posibles de comunicación.


 Recurso: realización concreta de un mecanismo.
 Instancia: cada utilización del recurso por un proceso.

CARACTERÍSTICAS COMU NES DE LOS MECANISMOS IPC DEL SYSTEM V


 Cada tipo de mecanismo tiene una entrada en una tabla en el espacio de memoria del núcleo.
 Cada tabla tiene un número de entradas configurable para las instancias.
 Cada entrada de la tabla tiene una llave numérica.
 Cada entrada tiene un índice.
 Cada entrada almacena una estructura ipc_perm que almacena información relativa al
propietario del recurso, al creador, el modo de acceso y la llave de acceso.
 Cada entrada tiene además otras informaciones como el PID del último proceso en usarla.
 Cada instancia tiene asignado un descriptor numérico.
 Cada mecanismo dispone de una llamada tipo get.
 Cada mecanismo dispone de una llamada tipo ctl.

ASIGNACIÓN DE UN ÍND ICE I T A UNA INSTANCIA N I P C


El núcleo calcula el descriptor numérico NIPC que asigna a una instancia de un

mecanismo IPC usando la siguiente fórmula:

NIPC = seq * NT + IT

El núcleo traduce el NIPC a la posición de la instancia en la tabla usando la fórmula:

IT = NIPC mod(NT) = NIPC % NT

CREACIÓN DE LLAVES
resultado=ftok(ruta,letra);

ALGUNOS COMENTARIOS SOBRE LAS LLAMADAS AL SISTEMA TIPO GET


IPC_CREAT pide al núcleo que cree la instancia si ésta no existe ya.

IPC_EXCL es utilizado junto con IPC_CREAT y pide al núcleo que devuelva un error si la instancia ya
existía.

Si la llave toma el valor especial IPC_PRIVATE, el núcleo crea una nueva instancia.
70
ALGUNOS COMENTARIOS SOBRE LAS LLAMADAS AL SIS TEMA TIPO CTL
Comandos de control: IPC_STAT y IPC_SET para obtener y configurar información del estado de un
recurso e IPC_RMID para eliminar un recurso.

SEMÁFOROS

Wait_sem()

Signal_sem()

Semid hace referencia a un conjunto de semáforos en cada entrada de la tabla de semáforos con
información de la estructura semid_ds.

CREACIÓN Y OBTENCIÓN DE UN CONJUNTO DE SEMÁFOROS


semid=semget(key,count,flags);

REALIZACIÓN DE OPERA CIONES CON LOS ELEMENTOS DE UN C ONJUNTO DE SEMÁFOROS


resultado=semop(semid, sops, nsops);

La definición de la estructura del tipo sembuf utilizada es:

struct sembuf{

unsigned short sem_num;

short sem_op;

short sem_flg;

ACCESO A LA INFORMACIÓN ADMINISTRATIVA Y DE CONTROL DE UN CONJUNTO DE


SEMÁFOROS
resultado=semctl(semid, semnum, cmd, arg);

COLAS DE MENSAJES

El mecanismo de comunicación de las colas de mensajes corresponde a la implementación del concepto


de buzón, que permite la comunicación indirecta entre procesos.

ESTRUCTURAS DE DATOS ASOCIADAS A LOS MENSAJES


Mensaje = tipo de mensaje + texto o cuerpo del mensaje.

Cada entrada de la tabla de colas de mensajes tiene asignada una única cola msqid con msqid_ds
(derechos de acceso, punteros al primer y último mensaje, bytes totales en la cola, etc).

Cada cola tiene asociada una lista enlazada de cabeceras de mensajes.

CREACIÓN U OBTENCIÓN DE UNA COLA DE MENS AJES


msqid=msgget(key,flags)

71
ENVÍO DE MENSAJES
resultado=msgsnd(msqid,&buffer,msgsz,msgflags);

buffer es una estructura de datos:

struct {

long msg_type;

char msg_sopt[100];

} buffer;

Llamada al sistema bloqueante msgsnd.

RECEPCIÓN DE MENSAJE S
Llamada al sistema bloqueante msgrcv.

resultado=msgrcv(msqid,&buffer,msgsz,msgtipo,msgflags);

El argumento msgtipo puede tomar los siguientes valores:

 msgtipo = 0. Se extrae el primer mensaje que haya en la cola independientemente de su tipo.


Corresponde al mensaje más viejo.
 msgtipo > 0. Se extrae el primer mensaje del tipo msgtipo que haya en la cola.
 msgtipo < 0. Se extrae el primer mensaje que cumpla que su tipo es menor o igual al valor
absoluto de msgtipo y a la vez sea el más pequeño de los que hay.

ACCESO A LA INFORMACIÓN ADMINISTRATIVA Y DE CONTROL DE UNA COLA DE MENSAJES


La llamada al sistema msgctl permite leer y modificar la información estadística y de control de una cola
de mensajes, su declaración es:

resultado=msgctl(msqid, cmd, &buffer);

DISCUSIÓN

MEMORIA COMPARTIDA

ESTRUCTURAS DE DATOS UTILIZADAS PARA COMPARTIR MEMORIA


Tabla de memoria compartida, cada entrada es una región de memoria compartida shmid con una
estructura de datos shmid_ds (con permisos, tamaño, procesos participantes y fechas; un puntero a la
tabla de regiones).

CREACIÓN U OBTENCIÓN DE UNA REGIÓN DE MEMORIA COMPARTIDA


shmid=shmget(key,size,flags);

Heredado por procesos descendientes.

72
Asigna una región mediante el uso del algoritmo allocreg().

LIGAR UNA REGIÓN DE MEMORIA COMPARTIDA AL ESPACIO DE DIRECCI ONES VIRTUALES


DE UN PROCESO
resultado=shmat(shmid,shmdir,shmflags);

Si shmdir = 0, el sistema selecciona la dirección. Es la opción más adecuada si se desea conseguir


portabilidad.

DESLIGAR UNA REGIÓN DE MEMORIA COMPARTID A DEL ESPACIO DE DIRECCIONES


VIRTUALES DE UN PROCESO
resultado=shmdt(shmdir);

ACCESO A LA INFORMACIÓN ADMINISTRATIVA Y DE CONTROL DE UNA REGIÓN DE


MEMORIA COMPARTIDA
resultado=shmctl(shmid,cmd,&buffer);

MECANISMOS DE SINCRONIZACIÓN TRADICIONALES

NÚCLEO NO EXPROPIABLE

La primera medida de seguridad que utiliza UNIX es asegurar la no expropiabilidad del núcleo. Es decir,
cualquier proceso ejecutándose en modo núcleo continuará ejecutándose, incluso aunque su cuanto
haya expirado, hasta que vuelva a modo usuario o entre en el estado dormido en espera de algún
recurso que se encuentra ocupado. Esto permite al código del núcleo manipular las estructuras de datos
sin necesidad de bloquearlas, sabiendo que ningún otro proceso podrá acceder a ellas hasta que el
proceso actual haya terminado de utilizarlas y esté listo para ceder el núcleo en un estado consistente.

BLOQUEO DE INTERRUPCIONES

Para proteger una región crítica se eleva el npi para bloquear interrupciones que puedan afectarla.

USO DE LOS INDICADORES BLOQUEADO Y DESEADO

LIMITACIONES

SEGUIMIENTO DE PROCESOS

ptrace(cmd,id,addr,data);

MECANISMOS DE SINCRONIZACIÓN MODERNOS

SEMÁFOROS

Implementación con exclusión mutua sobre un recurso.

init_sem(semid,1);

73
wait_sem(semid);

/*sección crítica */

signal_sem(semid);

CERROJOS CON BUCLE DE ESPERA

Un cerrojo con bucle de espera (spin locks) es una primitiva muy simple que permite el acceso en
exclusiva a un recurso.

Si un recurso está protegido por un cerrojo, un proceso intentando acceder a un recurso no disponible
estará ejecutando un bucle, lo que se denomina espera ocupada, hasta que el recurso esté disponible.

Un cerrojo suele ser una variable escalar que vale 0 si el recurso está disponible y que vale 1 si el recurso
no está disponible.

Poner a 1 el cerrojo significa “cerrar el cerrojo” y ponerlo a 0 significa “abrir el cerrojo”.

La variable es manipulada usando un bucle sobre una instrucción atómica del tipo comprobar-configurar
(test_and_set).

VARIABLES DE CONDICI ÓN

Mecanismo asociado con un predicado basado en algún dato compartido. Permite a un proceso
bloquearse en función de su valor y despierta a uno o todos los procesos bloqueados cuando el
resultado del predicado cambia. Más útili para espera de eventos que control de acceso a recursos.

RESUMEN TEMA 6

UNIX es un sistema operativo multiproceso. Por tanto los procesos requieren comunicación y
sincronización entre sí, para conseguir distintos objetivos: transferencia y compartir datos, notificación
de eventos, compartir recursos y control de procesos. En este tema, se estudian los mecanismos
adecuados que debe disponer el núcleo para implementar la comunicación y sincronización entre los
procesos.

1.Las primeras distribuciones de UNIX únicamente disponían de tres mecanismos IPC universales para la
comunicación entre procesos: las señales, las tuberías y el seguimiento de procesos.

Las señales se utilizan principalmente para notificar a un proceso eventos asíncronos. Como mecanismo
IPC, las señales poseen varias limitaciones: son costosas, ancho de banda limitado, y limitación en la
información a transportar. Por tanto, resultan poco útiles como mecanismo IPC:

Las tuberías son un mecanismo de comunicación unidireccional, que permite la transmisión de un flujo
de datos no estructurado. Un proceso emisor escribe datos en un extremo de la tubería y otro proceso
receptor puede leer estos datos en el otro extremo, y una vez leídos son borrados. Existen dos tipos:
tuberías sin nombre y ficheros FIFO.

Las tuberías sin nombre se crean mediante la invocación a la llamada al sistema pipe, y solo puede
usarse por el proceso que hace la llamada y sus descendientes. Como mecanismo IPC, las tuberías
proporcionan una forma eficiente de transferir datos de un proceso a otro, pero poseen limitaciones,
pues no puede ser usada para transmitir datos a múltiples procesos, o que no se puede determinar
cuántos mensajes han sido enviados y el envío se realiza en una única operación. Existen varias formas

74
de implementar las tuberías: sistema de ficheros con asociación de un nodo-i y una entrada en la tabla
de ficheros o conectores (sockets). SVR4 proporcional tuberías bidireccionales basadas en stream.

Las tuberías con nombre o ficheros FIFO se crean invocando a la llamada al sistema mknod y pueden ser
utilizadas por cualquier proceso siempre que disponga de los permisos adecuados. Tienen la ventaja
frente a las tuberías sin nobre que poseen un nombre, pueden ser accedidos por procesos sin relación
familiar, y son persistentes.

La E/S en una tubería es como la E/S en un fichero, y por tanto se realiza también mediante las llamadas
al sistema read y write sobre los descriptores de la tubería.

Otro mecanismo disponible es el seguimiento de procesos. La llamada al sistema ptrace suministra un


conjunto se servicios para el seguimiento, que se usa principalmetne para programas depuradores.

2.Los mecanismos IPC del System V (semáforos, colas de mensajes y memoria compartida) vinieron a
satisfacer las necesidades de muchas aplicaciones y que no resolvían los mecanismos universales antes
mencionados. Estos mecanismos están implementados como una unidad y tienen las siguientes
características comunes: cada tipo tiene asignada una tabla en el espacio de memoria de tamaño fijo.
Cada tabla asignada tiene un número de entradas configurable, una llave numérica, un índice IT y una
estructura ipc_perm, y otras informaciones como el pid del último proceso. También cada instancia
tiene asignado un descriptor numérico, y dispone de llamadas al sistema tipo get para crear una nueva
instancia, y tipo ctl para acceder a la información administrativa y de control.

Los semáforos son objetos que pueden tomar valores enteros que soportan dos operaciones atómicas:
P() y V(). La operación P() decrementa en una unidad el valor y bloquea al proceso que solicita la
operación si su nuevo valor es menor que cero. La operación V() incrementa en una unidad el valor; si el
valor resultante es mayor o igual a cero, despierta a los procesos que estuvieran esperando. En el
capítulo se estudian asimismo las llamadas al sistema: semget para crear un conjunto de semáforos;
semop para realizar operaciones sobre los elementos de un semáforo, y semctl para acceder a la
información de control y administrativa.

Una cola de mensajes es una estructura de datos gestionada por el núcleo, donde pueden escribir varios
procesos. En la implementación del UNIX System V todos los mensajes son almacenados en el espacio
del núcleo y tienen asociado un identificador de cola de mensaje denominado msgid.

Un mensaje se implementa mediante una estructura que consta de dos campos: el tipo y el texto. El
núcleo mantiene básicamente tres tipos de estructuras de datos para implementar las colas de
mensajes: la tabla de colas de mensajes, la lista enlazada de cabeceras de mensajes asociadas a una cola
y un área de datos. En el capítulo se estudian las llamadas al sistema: msgget para crear una cola;
msgsnd para enviar un mensaje, msgrcv para extraer un mensaje, msgctl para leer y modificar la
información de control.

La forma más rápida de comunicar dos procesos es la memoria compartida. Para enviar datos de un
proceso a otro, el proceso emisor solamente tiene que escribir en memoria y automáticamente esos
datos estarán disponibles para que los lea otro proceso.

El núcleo posee una tabla de memoria compartida, donde cada entrada está asignada a una región de
memoria compartida que viene identificada por un descriptor numérico shmid. Igualmente, el capítulo
presenta las llamadas shmget para crear un segmento de memoria compartida, shmat para asignar un
espacio de direcciones virtuales; shmdt para que un proceso se desuna a un segmento; shmctl para
realizar operaciones de control.

75
3 Los mecanismos de sincronización tradicionales son: el núcleo no expropiable, el bloqueo de
interrupciones, y el uso de los indicadores bloqueado y deseado. En multiprogramación, varios procesos
comparten el núcleo, por lo que este debe sincronizar el acceso a sus estructuras. La primera medida es
asegurar la no expropiabilidad, donde cualquier proceso ejecutándose en modo núcleo continuará su
ejecución hasta que vuelva a modo usuario o entre el estado dormido.

Aunque un proceso en modo núcleo no puede ser expropiado sí puede ser interrumpido. El núcleo debe
sincronizar el acceso a los datos utilizados tanto por el código normal como por el manipulador de
interrupciones, por lo que UNIX suministrar un mecanismo para bloquear mediante la manipulación del
npi.

A menudo un proceso quiero asegurarse el uso exclusivo de un determinado recurso aunque esté en
estado dormido. UNIX asocia dos indicadores: bloqueado y deseado, a cada recurso compartido.

4. Por último, el capítulo presenta los mecanismos de sincronización modernos de UNIX: semáforos,
cerrojos con bule de espera, que permite el acceso en exclusiva a un recurso; y las variables de
condición, mecanismo asociado con un predicado, que permite a un proceso bloquearse en función de
su valor y suministra los servicios para despertar a uno o todos los procesos bloqueados.

EJERCICIOS TEMA 6

76
TEMA 7: GESTIÓN DE MEMORIA EN
UNIX
INTRODUCCIÓN

ESTRUCTURAS DE DATOS ASOCIADAS A LAS GES TIÓN DE MEMORIA MEDIANTE DEMANDA


DE PÁGINAS EN EL SVR3.

RELACIÓN ENTRE REGIONES Y PÁGINAS: TABLAS DE PÁGINAS

TABLA DE DESCRIPTORES DE BLOQ UES DE DISCO

TABLA DE DATOS DE MARCOS DE PÁGINA

TABLA DE INTERCAMBIO

FORK() EN UN SISTEMA CON PAGINACIÓN

EXEC() EN UN SISTEMA DE PAGINACIÓN

TRANSFERENCIA DE PÁGINAS DE MEMORIA PRINCIPAL AL ÁREA DE INTERCAMBIO

El ladrón de páginas.

TRATAMIENTO DE LOS FALLOS DE PÁGINA

EL MANIPULADOR DE FALLOS DE VALIDEZ

MANIPULADOR DE FALLO S DE PROTECCIÓN

77
EXPLICACIÓN DESDE EL PUNTO DE VISTA DE LA GESTIÓN DE MEMORIA DEL
CAMBIO DE MODO DE UN PROCESO

LOCALIZACIÓN EN MEMORIA DEL ÁREA U DE UN PROCESO

RESUMEN TEMA 7

1. La memoria principal o física es la memoria de acceso aleatorio (RAM). Esta memoria tiene un tiempo
de acceso menor, es más costosa y de menor capacidad que la memoria secundaria (discos duros,
máquinas en red). Cuando el sistema arranca, el núcleo reserva parte de la memoria principal para su
código y estructuras de datos estáticas. El resto de la memoria se administra dinámicamente, asignando
porciones de memoria entre procesos y subsistemas del núcleo, y la libera cuando ya no se necesita.

El subsistema de administración de memoria es la parte del núcleo responsable de gestionar la memoria


principal, e interactúa con la unidad de administración de memoria (MMU), cuya tarea principal es la
traducción de direcciones virtuales (mediante tablas de páginas y TLB). Las primeras implementaciones
de UNIX empleaban para administrar la memoria una política de intercambio; donde solo pocos
procesos podían estar cargados al mismo tiempo en memoria principal. Más tarde, apareció la política
mediante demanda de página; donde la memoria principal se divide en bloques de tamaño fijo (página
física o marco de página); a la vez que los procesos se dividen en páginas, que son las cargadas en los
marcos de páginas conforme son requeridas. Así, la memoria principal contiene algunas de las páginas
de cada proceso, que hace que varios procesos puedan estar activos al mismo tiempo.

Como UNIX es un sistema de memoria virtual, las direcciones del programa son virtuales y son divididas
por la MMU en un número de página virtual y un desplazamiento desde el origen de la página. La MMU,
junto con el sistema operativo, traduce el número de página virtual en el espacio de direcciones del
programa a un número de marco de página para acceder a la localización adecuada.

Otra política de gestión de memoria que se combina con la paginación es la segmentación, que divide el
espacio de direcciones de un proceso en varios segmentos, descrito cada uno de ellos por un descriptor
que contiene la dirección física base en la que es cargado, su tamaño y su protección.

2. El capítulo se centra en la política de gestión de memoria mediante demanda de página


implementada en SVR3. El núcleo mantiene fundamentalmente cuatro tipos de estructuras de datos
para implementar la política de memoria mediante demanda de página: las tablas de páginas, las tablas
de descriptores de bloques de disco (dbd), la tabla de datos de los marcos de página (dmp) y la tabla de
intercambio.

Las tablas de páginas (almacenadas en memoria principal) relaciones regiones y páginas, existiendo una
tabla de páginas por cada entrada de la tabla de regiones. Como ya aprendimos en capítulos anteriores,
cada proceso tiene asignada una tabla de regiones de proceso, donde cada una de las entradas contiene
la dirección virtual de comienzo y un puntero que señala a la tabla de regiones. En una arquitectura con
páginas, cada región se divide en múltiples páginas, y así cada entrada de la tabla de regiones contiene
un puntero a una tabla de páginas. Cada entrada de una tabla de páginas contiene los campos: dirección
física de inicio de una página, edad, copiar al escribir, modificada, referenciada, válida, bits de
protección.

78
Cada una de las tablas de páginas tiene asignada una tabla de descriptores de bloques de disco (tabla
dbd). El número de entradas de una tabla dbd es igual al número de entradas de la tabla de páginas a la
que está asignada. La entrada de una tabla dbd tiene información sobre la copia en memoria
secundaria, y presenta los campos: dispositivo de intercambio, número de bloque y tipo. Los procesos
que comparten una región acceden a las mismas entradas de las tablas de páginas y descriptores de los
bloques de disco. El contenido de una página virtual está o bien en un bloque particular en un
dispositivo de intercambio, o bien en un bloque de un fichero ejecutable en el disco.

La tabla de datos de marcos de páginas (tabla dmp) del núcleo se inicializa al arrancar el sistema y
describe cada marco de página de memoria principal. Cada entrada de esta tabla posee los siguientes
campos: estado de página, contador de referencias, dispositivo lógico, punteros a otras entradas de la
tabla dmp. Cuando se requiere un marco de página libre, el núcleo accede a lista de marcos libres,
elimina la entrada de la tabla dmp situada a la cabeza de la lista, actualiza su número de dispositivo y
número de bloque y la pone en la cola de dispersión correcta.

Por último, el núcleo dispone de una tabla de intercambio que contiene una fila por cada copia de una
página situada en un dispositivo de intercambio. En cada fila hay un contador de referencias que indica
el número de entradas de las tablas de páginas que apuntan a una misma copia de página situada en un
dispositivo de intercambio.

3. Como ya se vio en capítulos anteriores, en la llamada al sistema fork el núcleo duplica cada región del
proceso padre y se la asigna al proceso hijo. En el sistema de paginación del System V, el núcleo evita
realizar la copia del espacio de direcciones del padre mediante la adecuada manipulación de la tabla de
regiones, las tablas de páginas y la tabla dmp. El núcleo incrementa el contador de referencias en la
tabla de regiones de las regiones compartidas, mientras que para regiones privadas (región de datos,
pila) el núcleo asigna una nueva entrada de la tabla de regiones y una nueva tabla de páginas y después
examina cada entrada de la tabla de páginas del padre. Si una página es válida, incrementa el contador
de referencias de la entrada de la tabla dmp. Además, si la página existe en un dispositivo de
intercambio, incrementa el contador de entradas de la tabla de intercambio.

4. Cuando un proceso invoca a la llamada al sistema exec, el núcleo carga el fichero ejecutable en
memoria principal desde el sistema de ficheros. En un sistema con paginación, el núcleo no preasigna
memoria al fichero ejecutable, sino que se la va asignando según se van produciendo fallos de página.
En primer lugar, asigna las tablas de páginas y las tablas dbd para las regiones del fichero ejecutable y va
marcando las entradas de las tablas dbd como DF o DZ. Cuando el núcleo va cargando el fichero
ejecutable en memoria, el proceso incurre en un fallo de página en cada lectura de página. El
manipulador de fallos comprueba si la página es DF o DZ para realizar en cada caso las acciones
oportunas. Si no existe espacio libre en memoria, el proceso del núcleo denominado ladrón de páginas
periódicamente intercambiará páginas a memoria secundaria para hacer sitio para el fichero.

5. En cuanto a la transferencia de páginas de memoria principal al área de intercambio, el ladrón de


páginas es el encargado de realizar la transferencia de las páginas que ya no forman parte del conjunto
de trabajo de un proceso. El núcleo crea el ladrón de páginas en la inicialización del sistema y lo invoca
cuando disminuye el número de páginas físicas libres. El ladrón de páginas se ejecutará hasta conseguir
el valor máximo de espacio libre.

6. Por otro lado, el sistema puede incurrir en dos tipos de fallos de página: fallos de validez y fallos de
protección. Un fallo de validez se produce cuando un proceso intenta acceder a una página cuyo bit
válida no está activado. Un fallo de protección se produce cuando un proceso intenta acceder a una
página válida cuyos bits de protección no permiten acceder a la página, o cuando intenta escribir una
página cuyo bit copiar al escribir esté activado.

79
7. En muchas máquinas, el espacio de direcciones virtuales de un proceso es dividido en varias clases
(incluyendo sistema y usuario) donde cada una tiene su propia tabla de páginas. Cuando se ejecuta en
modo núcleo, el sistema permite el acceso a las direcciones del núcleo. El acceso a estas direcciones
está prohibido cuando se ejecuta en modo usuario. Cuando se cambia de modo usuario a modo núcleo
como resultado de una interrupción o una llamada al sistema, el sistema operativo permite referencias a
las direcciones del núcleo, y cuando se vuelve de modo núcleo a modo usuario se prohíben tales
referencias.

8. Por último, se estudia la localización en memoria del área U de un proceso. Como ya se estudió, cada
proceso tiene su propia área U. Si embargo, el núcleo únicamente puede acceder al área U del proceso
actual. El núcleo camba su mapa de traducción de direcciones virtuales de acuerdo con el proceso que
se está ejecutando.

EJERCICIOS TEMA 7

80
TEMA 8: SISTEMAS DE ARCHIVOS EN
UNIX
INTRODUCCIÓN

Un sistema de ficheros permite realizar una abstracción de los dispositivos físicos de almacenamiento
de la información para que sean tratados a nivel lógico.

Sistema de ficheros del System V – s5fs – para versiones System V y anteriores a BSD 4.2. – Local.

Sistema de ficheros rápido – FFS – a partir de BSD 4.2, SVR4. – Local.

Son sistemas generales para aplicaciones de tiempo compartido. Los sistemas modernos usan técnicas
sofisticadas que suministran un mejor comportamiento, mayor seguridad y disponibilidad.

Sistemas de ficheros distribuidos: NFS, RFS y AFS.

La interfaz nodo-v/sfv de Sun introdujo los conceptos de nodo virtual (nodo-v) y sistema de ficheros
virtual (sfv), que permite trabajar con sistemas de ficheros distribuidos o con sistemas de ficheros de
otros sistemas operativos de forma transparente, como si fueran locales.

FICHEROS ESPECIALES

Los ficheros especiales o ficheros de dispositivos permiten a los procesos comunicarse con los
dispositivos periféricos. Se suelen almacenar en /dev.

Dos tipos de periféricos:

 Dispositivos modo bloque: discos, CD-ROOM, … Utilizan caché de buffers de bloques.


 Dispositivos modo carácter: terminales, impresoras, ratón, …

También se soportan dispositivos software o pseudodispositivos, usando las mismas llamadas al


sistema para el manejo de ficheros ordinarios pero sobre el fichero de dispositivo /dev/mem – fichero
de dispositivo genérico para acceder a memoria.

El concepto de fichero incluye todo tipo de objetos relativos a E/S. Son accedidos a través de
descriptores de ficheros y se aplican las llamadas al sistema ordinarias. Algunos objetos de E/S no
soportan todas las operaciones con ficheros. Las aplicaciones a menudo necesitan verificar – fstat – a
qué tipo de fichero están accediendo.

El nodo-i de los ficheros de dispositivo no referencia bloques de datos, contiene dos números:

 El número principal – major number – indica el tipo de dispositivo.


 El número secundario – minor number – número de unidad dentro del dispositivo, la instancia
específica del dispositivo.

Los dispositivos de modo bloque y los dispositivos de modo carácter tienen conjuntos de números
principales independientes.

El núcleo mantiene dos tablas con estructuras que almacenan punteros a la colección de rutinas del
driver o manejador de cada dispositivo:

81
 Tabla de conmutación de dispositivos modo bloque
 Tabla de conmutación de dispositivos modo carácter

Acciones del núcleo en invocaciones de llamadas al sistema sobre ficheros de dispositivo:

1. Usa el descriptor del fichero para localizar el objeto de fichero abierto.


2. Comprueba que el objeto de fichero puede ser leído.
3. Obtiene del objeto de fichero abierto el puntero al nodo-i en memoria – nodo-im: copia del
nodo-i más otras informaciones.
4. Bloquea el nodo-im, exclusividad de acceso.
5. Comprueba campo modo del nodo-im y saca el tipo de fichero.
6. Utiliza el número principal y secundario para encontrar en la tabla de conmutación de
dispositivos las rutinas de su manejador.
7. Invoca la rutina correspondiente a la llamada realizada.
8. Desbloquea el nodo-im y devuelve el resultado al usuario.

MONTAJE DE SISTEMAS DE FICHEROS

CONSIDERACIONES GENE RALES

LLAMADAS AL SISTEMA Y COMANDOS ASOCIADOS AL MONTAJE DE SISTEM AS DE


FICHEROS

resultado = mount(dispositivo,dir,flags);

resultado = mount(dispositivo,dir,flags,tipo,dataptr,datalon);

resultado = umount(dispositivo);

$ mount dispositivo dir

$ mount arg

$ umount dispositivo

ENLACES SIMBÓLICOS

Enlace duro:

$ ln fichero enlace

symlink(fichero,enlace)

Enlace simbólico:

$ ln -s fichero enlace

LA CACHÉ DE BUFFERS DE BLOQUES

FUNCIONAMIENTO BÁSIC O

82
CABECERAS DE LOS BUFFERS

VENTAJAS

INCONVENIENTES

LA INTERFAZ NODO-V/SFV

Sun Microsystems introdujo la interfaz nodo-v/sfv (nodo virtual/sistema de ficheros virtual) para
suministrar un marco de trabajo en el núcleo que permitiera el acceso y la manipulación de diferentes
tipos de sistemas de ficheros.

UNA BREVE INTRODUCCI ÓN A LA PROGRAMACIÓN ORIENTADA A OBJETOS

PERSPECTIVA GENERAL DE LA INTERFAZ NODO -V/SFV

La abstracción nodo virtual (nodo-v) representa a un fichero en el núcleo de UNIX. Por su parte, la
abstracción sistema de ficheros virtual (sfv) representa a un sistema de ficheros.

LA CLASE NODO-V

LA CLASE SFV

NODOS VIRTUALES Y FI CHEROS ABIERTOS

EL CONTADOR DE REFERENCIAS DEL NODO-V

EL SISTEMA DE FICHER OS DEL UNIX SYSTEM V (S5FS)

ORGANIZACIÓN EN EL DISCO DEL S5FS


DIRECTORIOS
NODOS-I
EL SUPERBLOQUE
ORGANIZACIÓN EN LA MEMORIA PRINCIPAL DEL S5FS
BÚSQUEDA DE NODOS -IM
ASIGNACIÓN Y RECUPERACIÓN DE NODOS-IM

83
ANÁLISIS DEL S5FS

COMPROBACIÓN DEL ESTADO DE UN SISTEMA DE FICHEROS

$ fsck [-opciones] [sistema...]

CONSIDERACIONES ADICIONALES SOBRE LA INTERFAZ NODO-V/SFV DEL SVR4

PARTES DEPENDIENTES DEL SISTEMA DE FICHEROS DE UN OBJETO NODO-V


EL CONMUTADOR DEL SI STEMA DE FICHEROS VI RTUAL
IMPLEMENTACIÓN DE MO UNT
PROCESAMIENTO VFS_MOUNT
ANÁLISIS DE RUTAS DE ACCESO
LA CACHÉ DE BÚSQUEDA DE NOMBRES EN DIREC TORIOS
LA OPERACIÓN VOP_LOO KUP
APERTURA DE UN FICHERO

EL SISTEMA DE FICHEROS FFS (O UFS)

ORGANIZACIÓN
POLÍTICAS DE ASIGNACIÓN
MEJORAS EN LA FUNCIONALIDAD DE UN SISTEMA DE FICHEROS FFS
ANÁLISIS

CARACTERÍSTICAS DE ALGUNOS SISTEMAS DE ARCHIVOS MODERNOS

TRANSACCIONES

JOURNALING

COPY-ON-WRITE Y SNAPSHOTS
ESPACIOS DE ALMACENAMIENTO

RESUMEN TEMA 8

1. Un sistema de ficheros es una abstracción del almacenamiento que permite trabajar con la
información sin necesidad de conocer los detalles de bajo nivel de los dispositivos. Los datos son
tratados a nivel lógico, como una estructura de alto nivel organizada de forma jerárquica en archivos y
directorios.

En UNIX los dispositivos son tratados como archivos especiales, de este modo se puede acceder a un
disco, un cdrom, o a la memoria de los procesos leyendo un archivo (/proc). Los archivos pueden ser de
modo bloque (como los discos) o de modo carácter (como impresoras o terminales). El directorio /dev
contiene todos los archivos de dispositivo.

A cada archivo se asocia una estructura de datos llamada nodo-i que contiene la información necesaria
para acceder al archivo (como por ejemplo la dirección de los bloques que contiene). A cada nodo-i se le
asocia un número de nodo-i que permite identificar a un archivo. Cuando el archivo es un dispositivo el

84
nodo-i contiene el número principal (que indica el tipo de dispositivo) y el número secundario que
distingue a los dispositivos del mismo tipo. El sistema utiliza el número principal para seleccionar el
driver adecuado para la operación de lectura o escritura.

Un directorio es una estructura que permite organizar jerárquicamente el sistema de archivos. A nivel
lógico un directorio es un contenedor de archivos o directorios. De este modo la estructura del sistema
de archivos es un árbol que parte del directorio raíz /.

Desde el punto de vista físico un directorio es un archivo especial que contiene una lista de nombres y
números de nodo-i de los archivos contenidos en el mismo. Esto permite al sistema operativo realizar la
conversión entre el nombre y el nodo-i correspondiente. El directorio contiene también el nodo-i de el
mismo “.” y del directorio que lo contiene “..”

2. Un disco físico es un dispositivo de modo bloque que almacena un array de bloques. El espacio de
almacenamiento del disco puede dividirse en particiones mediante el comando fdisk. Cada partición es
tratada como un disco lógico y en ella se puede crear un sistema de archivos con newfs o mkfs. La
partición que almacena el arranque es la partición activa. La partición que almacena el área de
intercambio es la partición swap.

En UNIX la estructura del sistema de archivos no es rígida sino que se construye sobre la marcha
mediante un procedimiento de montaje. El proceso de montaje parte de un directorio raíz / y agrega los
archivos que se encuentran en un disco lógico a la estructura de archivos general en un directorio
llamado punto de montaje. Para ello se usa el comando mount.

De forma automática, durante el arranque UNIX monta todos los sistemas de ficheros definidos en el
archivo /etc/mtab.Sólo el superusuario puede modificar este archivo y en el mismo se definen los
permisos de cada sistema de archivos y las operaciones que cada usuario puede realizar sobre él.

3. En UNIX un mismo fichero puede tener varios nombres, cada uno de ellos se denomina enlace duro.
Todos los enlaces duros apuntan al mismo nodo-i y dicho nodo-i tiene un contador de referencias.
Cuando el contador de referencias es 0 el fichero puede borrarse.

Otra forma de acceder a un fichero desde varios directorios es usar un enlace simbólico (link). El enlace
simbólico contiene la ruta del fichero al que apunta. Como el enlace simbólico no contiene un enlace el
nodo-i se pueden crear enlaces entre sistemas de ficheros distintos. El problema de los enlaces es que si
el fichero se cambia de nombre o posición el enlace se rompe y deja de funcionar.

Para crear enlaces se usa ln [–s] fichero enlace donde la opción –s establece que el enlace sea simbólico
(en caso contrario es un enlace duro).

4. El acceso al disco es muy lento comparado con la memoria principal, por ese motivo los sistemas de
archivos utilizan la memoria principal como caché para acceso al disco a este mecanismo se llama caché
de buffers de bloques.

La caché de buffers de bloques mantiene una estructura en memoria organizada en colas de dispersión
doblemente enlazadas lo que hace rápida la búsqueda de los bloques. Cada entrada de la cola contiene
una copia de los bloques de disco y un bit de control B_DELWRI que indica si el bloque está “sucio”.
Cuando el sistema necesita leer un bloque busca el bloque primero en la cola de dispersión
correspondiente y si no lo encuentra lo lee del disco y lo coloca en la cola.

Generalmente los programas modifican un disco más de una vez por lo que se implementa una post-
escritura, esto significa que las modificaciones no se aplican inmediatamente al disco sino que se escribe
en el buffer y se marca como “sucios”.

85
El núcleo mantiene una lista doblemente enlazada con los buffers libres y la utiliza para localizar buffers
libres cuando necesita leer bloques de archivo nuevos. Cuando es necesario liberar espacio en la caché
se buscan bloques limpios, si un bloque está “sucio” se pone en la cola de escritura del disco para
actualizar el contenido en el disco antes de borrarlo de la caché.

El problema principal de la caché de buffers de bloques es la coherencia en el disco ya que si se cuelga el


sistema o una unidad no se desmonta adecuadamente los bloques que estaban en memoria no se han
actualizado en el disco. Además si se lee un archivo de gran tamaño secuencialmente y los bloques no se
reutilizan puede vaciarse la caché lo que disminuye la eficiencia.

5. La interfaz nodo-V/SVF es una interfaz estándar al sistema de ficheros que se introdujo en el System V
y permite que el núcleo gestione de una forma idéntica varios sistemas de ficheros tanto locales como
remotos de forma homogénea y modular. La interfaz define las operaciones a realizar en el sistema de
archivos con independencia de la implementación concreta de las mismas.

Cuando se realiza una llamada al sistema que trabaja con ficheros el núcleo realiza las operaciones
independientes del sistema de ficheros y luego invoca las funciones correspondientes en la interfaz
nodo-V/SVF que se encarga de traducir cualquier operación del núcleo sobre un fichero (o sobre un
sistema de ficheros) a la función adecuada según el tipo de sistema de ficheros.

Para la construcción de la interfaz se utiliza el concepto de programación orientada a objetos, aunque el


lenguaje C lo permite explícitamente por lo que los objetos se implementaban usando punteros a
funciones.

La clase nodo-v abstrae el concepto de fichero abierto y contiene todas las operaciones que se realizan
sobre él. Contiene una base nodo-v con todos los datos independientes de la implementación y un
conjunto de funciones que se dividen en funciones virtuales (estructura de punteros a función). Las
funciones virtuales son siempre las mismas, pero su implementación depende del sistema de ficheros en
particular. También contiene un conjunto de rutinas de utilidad y macros que son específicas de cada
sistema y pueden ser usadas por otros subsistemas del núcleo.

La clase svf representa al sistema de ficheros activo y hay uno por cada sistema de ficheros activo.
Contiene los campos vfs_data y vfs_op donde la primera es independiente del sistema de ficheros y la
segunda contiene los punteros a las funciones dependientes del sistema de ficheros.

6. El sistema de ficheros s5fs se caracteriza por una estructura fija (área de arranque, superbloque, lista
de nodos-i y bloques de datos). El área de arranque contiene el código que se ejecuta cuando se inicia el
sistema. El superbloque alberga los metadatos del sistema de fichero (tamaño total, tamaño de los
bloques, número de bloques libres, etc…) y la primera parte de la lista enlazada de bloques libres. La
lista de nodos-i contiene todos los nodos-i del sistema de archivos mientras que los bloques de datos
albergan los archivos.

Los nodos-i se almacenan como una lista de indirección, las primeras 9 entradas de un nodo-i son
directas (apuntan directamernte al bloque de datos) la siguiente es indirecta simple (apunta a un bloque
que a su vez tiene punteros a bloques de datos) la siguiente indirecta doble (apunta a bloques que
apuntan a bloques de punteros a bloques de datos) y la siguiente es indirecta triple (apunta a bloques
que apuntan a bloques que a su vez apuntan a otros bloques que contienen punteros a los bloques de
datos) .

Los directorios son archivos que tienen una entrada 16 bytes por cada archivo que contienen el número
de nodo-i de 2 bytes (lo que limita el sistema a 65535 ficheros por partición) y el nombre de 14

86
caracteres. El sistema de ficheros utiliza la caché de buffers de bloques y a cada copia del nodo-i que se
encuentra en memoria se le llama nodo-im.

s5fs es sencillo pero tiene algunos problemas. Primero están las limitaciones en el tamaño del sistema
de ficheros y nombres, segundo que si se deteriora el superbloque se destruye el sistema de ficheros.

Además el rendimiento no es demasiado bueno por que nodos-i están lejos de los datos de modo que al
leer un archivo el cabezal de disco tiene que realizar muchos movimientos. Además la lista de bloques
libres se rellena en un orden aleatorio por lo que la asignación de espacio no es óptima.

7. UFS mejora s5fs en varios aspectos al tener en cuenta la geometría del disco en la asignación del
espacio. Para ello, divide las particiones crean grupos de cilindros llamados consecutivos llamados
exents e intenta escribir todos los datos relacionados en el mismo exent (como por ejemplo los nodos-i
y los bloques de datos). Además para proteger el sistema de ficheros contiene varias copias del
superbloque.

Por otra parte los bloques se dividen en framgentos lo que hace que se puedan usar tamaños de bloque
grandes sin desperdiciar mucho espacio. Cada archivo ocupa un conjunto de bloques completos y el
resto se guarda en fragmentos consecutivos de otro bloque.

Además UFS coloca los bloques consecutivos de datos en posiciones rotacionalmente óptimas, aumenta
el tamaño del nombre de un archivo a 255 bytes e implementa por primera vez los enlaces simbólicos.

8. Los sistemas de archivos modernos como ext4 , Btrfs, JFS, resiserFS, reiser 4, ZFZ o HAMMER. Tienen
características mejoradas como es la implementación de transacciones para resolver los errores de
lectura y escritura y mantener la coherencia del disco. Algunas implementacioes usan el registro por
diario o journaling y otras la técnica copy-on-write. En el segundo caso es posible crear instantáneas
(snapshots) del sistema de archivos con poco esfuerzo para restaurarlo a un punto anterior.

Además, algunos sistemas de archivos permiten crear espacios de almacenamiento o pools que
permiten utilizar varios discos y particiones como si se tratara de un único disco lógico. Esto permite
flexibilizar el almacenamiento, implementar políticas de replicación como por ejemplo RAID5 o RAID6 y
repartir la carga de trabajo entre varios discos aumentando el rendimiento.

EJERCICIOS TEMA 8

87
TEMA 9: GESTIÓN DE
ENTRADA/SALIDA EN UNIX
INTRODUCCIÓN

CONSIDERACIONES GENERALES

Un driver de dispositivo es una parte del núcleo que consiste en una colección de estructuras de datos y
funciones que controlan a uno o más dispositivos, e interactúa con el resto del núcleo mediante una
interfaz bien definida.

CONFIGURACIÓN DEL HARDWARE


INTERRUPCIONES ASOCIADAS A LOS DISPOSITI VOS

DRIVERS DE DISPOSITIVOS

CLASIFICACIÓN DE LOS DISPOSITIVOS Y DE LOS DRIVERS

Modo bloque. Caché de buffers de bloques.

Modo carácter.

Pseudodispositivos.

INVOCACIÓN DEL CÓDIG O DEL DRIVER


LOS CONMUTADORES DE DISPOSITIVOS
PUNTOS DE ENTRADA DE UN DRIVER

EL SUBSISTEMA DE ENT RADA/SALIDA

NÚMERO PRINCIPAL Y N ÚMERO SECUNDARIO DE UN DISPOSITIVO


FICHEROS DE DISPOSIT IVOS
EL SISTEMA DE FICHER OS SPECFS
EL NODO-S COMÚN

STREAMS

MOTIVACIÓN
CONSIDERACIONES GENERALES

RESUMEN TEMA 9

1. El subsistema de entrada/salida de UNIX se encarga de la transferencia de datos entre la memoria


principal y los dispositivos periféricos. UNIX ofrece un conjunto estándar de operaciones de
entrada/salida, pero cada dispositivo funciona de una forma distinta y requiere un código específico
para comunicarse con él.

88
Para que el diseñador núcleo no tenga que conocer todos los detalles de cada uno de los periféricos
existentes (lo cuál sería prácticamente imposible) se divide el problema de entrada/salida en dos partes.

Una parte es llevada a cabo por núcleo se denomina Subsistema de E/S y realiza todas las operaciones
independientes del dispositivo. La otra parte está formada por los drivers del dispositivo. Un driver es un
programa (típicamente creado por el fabricante del hardware) que proporciona las funciones básicas
para trabajar con él.

Para que el núcleo interactúe correctamente con los drivers existe una interfaz estándar de drivers de
dispositivo que cada driver debe implementar y cada driver es un módulo independiente que se enlaza
al núcleo.

2. La forma en la que el procesador se comunica con los dispositivos es a través del bus. El dispositivo se
conecta al bus a través de un dispositivo electrónico denominado controlador o adaptador.

La entrada salida puede ser controlada por programa o bien hacer uso del acceso directo a memoria. En
el primer caso esde readsdsafdfasdfsdfasf la CPU la que se encarga de ir recogiendo los datos del
controlador y ponerlos en la memoria. En el segundo caso la CPU envía una señal al controlador
indicando dónde debe colocar los datos del dispositivo, éste manipula directamente la memoria y
cuando acaba produce una señal de interrupción para que la CPU detecte el fin de la operación de E/S.

Como hay varios dispositivos que pueden producir interrupciones UNIX establece un conjunto de niveles
de prioridad de interrupción (npi). Las interrupciones se atienden de acuerdo a su prioridad de modo
que si el npi del sistema es inferior npi de la interrupción que llega no se detiene el trabajo en curso y se
deja para más tarde.

Cada interrupción tiene un código numérico llamado número del vector de interrupción, el núcleo utiliza
este número para buscar en una tabla de vectores de interrupción el vector de interrupción que apunta
a la rutina adecuada.

3. Los dispositivos se dividen en dispositivos modo bloque (que leen bloques de datos y los gestionan
por medio de la caché de buffers de bloque del núcleo) , dispositivos modo carácter (que son más lentos
al no existir un espacio intermedio de almacenamiento) y streams (que deriva de los drivers de
carácter). Existiendo una interfaz distinta para cada uno.

4. Un conmutador de dispositivo es una estructura de datos que define puntos de entrada para cada
dispositivo que debe soportar. Existen dos tipos de conmutadores: struct bdevsw para dispositivos
modo bloque y struct cdevsw para dispositivos modo carácter. Las operaciones básicas que
implemenrtan los drivers en el conmutador del dispositivo són:

d_open() y d_close() para iniciar y cerrar el dispositivo, y d_xhalt() para apagarlo. Cuando se trata de un
dispositivo de modo bloque se usa d_strategy() para leer y escribir, d_size() para determinar el tamaño
de una partición de disco, d_segmap() para traducir la memoria del dispositivo en una dirección del
espacio de direcciones del proceso o d_mmap() (Si no se suministra la rutina d_segmap()). Cuando se
está en modo bloque se usa d_read() y d_write()para leer, d_ioctl() como punto de entrada genérico
para operaciones de control y d_xpoll() para encuestar al dispositivo en busca de eventos.

5. El subsistema de E/S es la parte del núcleo que gestiona la parte independiente del dispositivo de la
E/S apoyándose en los drivers y se encarga de identificar los dispositivos mediante el número principal
(que especifica el tipo y por tanto el driver) y el secundario que identifica la instancia, ambos se
conminan en la variable dev_t.

89
El acceso a los dispositivos se realiza a través del sistema de archivos de modo que a cada dispositivo se
le hace corresponder un archivo especial creado con mknod y situado en el directorio /dev, en el nodo-i
correspondiente se encuentran los números principal y secundario.

Los dispositivos son tratados por la interfaz del sistema de ficheros nodo-v/svf como un sistema de
ficheros especial denominado specfs. En la práctica, es posible tener varios ficheros de dispositivos, cada
uno representando al mismo dispositivo por lo que se usa la noción de nodo-s común. La primera vez
que un usuario abre un fichero de dispositivo para un dispositivo en particular, el núcleo crea un nodo-s
y un nodo-s común que apunta al anterior. Si un usuario abre otro fichero que representa al mismo
dispositivo, el núcleo creará un nuevo nodo-s, que referenciará al mismo nodo-s común.

6. En las versiones de UNIX modernas se usa el concepto de streams para mejorar la interfaz de los
drivers, en especial las de modo carácter y los dispositivos de red y se usan además para implementar
los ficheros FIFO, tuberías y los conectores (sockets) para el trabajo en red.

Un stream es un procesamiento full-duplex y un camino de transferencia de datos entre un driver en el


espacio del núcleo y un proceso en el espacio de usuario. El stream estructura de forma modular y en
cada módulo hay una cola de lectura y otra de escritura. Los streams utilizan el paso de mensajes como
único mecanismo de comunicación.

Además los streams pueden multiplexarse, lo que significa que un driver de multiplexión puede conectar
múltiples streams en lo alto o en lo bajo, esto ocurre por ejemplo si se implementa TCP/IP con streams.
En este caso un mismo stream IP puede interactuar a la vez con varios drivers de bajo nivel en la capa
física y con varios drivers TCP para cada conexión.

EJERCICIOS TEMA 9

90

Вам также может понравиться