Características
Generales:
Es un sistema operativo
de tiempo
compartido, controla los recursos de una
computadora y
los asigna entre los usuarios. Permite a los usuarios correr sus
programas.
Controla los dispositivos de periféricos conectados a la
máquina.
Posee las siguientes características:
– Es un sistrema operativo multiusuario, con capacidad
de simular multiprocesamiento y procesamiento no
interactivo.
– Está escrito en un lenguaje de
alto nivel : C.
– Dispone de un lenguaje de
control
programable llamado SHELL.
– Ofrece facilidades para la creación de programas y
sistemas y el
ambiente
adecuado para las tareas de diseños de software.
– Emplea manejo dinámico de memoria por
intercambio o paginación.
– Tiene capacidad de interconexión de procesos.
– Permite comunicación entre procesos.
– Emplea un sistema
jerárquico de archivos, con
facilidades de protección de archivos,
cuentas y
procesos.
– Tiene facilidad para redireccionamiento de
Entradas/Salidas.
– Garantiza un alto grado de portabilidad.
El sistema se basa
en un Núcleo llamado Kernel, que reside permanentemente en
la memoria, y
que atiende a todas las llamadas del sistema,
administra el acceso a los archivos y el
inicio o la suspención de las tareas de los
usuarios.
La comunación con el sistema UNIX se da
mediante un programa de
control llamado
SHELL. Este es un lenguaje de
control, un
intérprete, y un lenguaje de
programación, cuyas características lo hacen sumamente flexible
para las tareas de un centro de cómputo. Como lenguaje de
programación abarca los siguientes
aspectos:
– Ofrece las estructuras de
control normales:
secuenciación, iteración condicional,
selección y otras.
– Paso de parámetros.
– Sustitución textual de variables y
Cadenas.
– Comunicación bidireccional entre
órdenes de shell.
El shell permite modificar en forma dinámica las características con que se ejecutan los
programas en
UNIX:
Las entradas y salidas pueden ser redireccionadas o
redirigidas hacia archivos,
procesos y
dispositivos;
Es posible interconectar procesos entre
sí.
Diferentes usuarios pueden "ver" versiones distintas del
sistema operativo
debido a la capacidad del shell para configurar diversos
ambientes de ejecución. Por ejemplo, se puede hacer que un
usuario entre directamente a su sección, ejecute un
programa en
particular y salga automáticamente del sistema al
terminar de usarlo.
El núcleo del Sistema
Operativo
El núcleo del sistema operativo
Unix (llamado
Kernel) es un programa escrito
casi en su totalidad en lenguaje C,
con excepción de una parte del manejo de interrupciones,
expresada en el lenguaje
ensamblador del procesador en el
que opera.
Las funciones del
núcleo son permitir la existencia de un ambiente en el
que sea posible atender a varios usuarios y múltiples
tareas en forma concurrente, repartiendo al procesador entre
todos ellos, e intentando mantener en grado óptimo la
atención individual.
El Kernel opera como asignador de recursos para
cualquier proceso que
necesite hacer uso de las facilidades de cómputo. Es el
componente central de Unix y tiene las
siguientes funciones:
– Creación de procesos, asignación de
tiempos de atención y sincronización.
– Asignación de la atención del procesador a los
procesos que lo requieren.
– Administración de espacio en el sistema de
archivos, que
incluye: acceso, protección y administración de usuarios; comunicación entre usuarios v entre
procesos, y manipulación de E/S y administración de periféricos.
– Supervisión de la transmisión de
datos entre
la memoria
principal y los dispositivos periféricos.
El Kernel reside siempre en la memoria
central y tiene el control sobre
la
computadora, por lo que ningún otro proceso puede
interrumpirlo; sólo pueden llamarlo para que proporcione
algún servicio de
los ya mencionados. Un proceso llama
al Kernel mediante módulos especiales conocidos como
llamadas al sistema.
El Kernel consta de dos artes principales: la
sección de control de procesos y la de control de
dispositivos. La primera asigna recursos,
programas,
procesos y atiende sus requerimientos de servicio; la
segunda, supervisa la transferencia de datos entre
la memoria
principal y los dispositivos periféricos. En términos generales,
cada vez que algún usuario oprime una tecla de una
terminal, o que se debe leer o escribir información del disco magnético, se
interrumpe al procesador
central y el núcleo se encarga de efectuar la
operación de transferencia.
Cuando se inicia la operación de la
computadora, debe cargarse en la memoria una
copia del núcleo, que reside en e] disco magnético
(operación denominada bootstrap). Para ello, se deben
inicializar algunas interfaces básicas de hardware; entre ellas, el
reloj que proporciona interrupciones periódicas. El Kernel
también prepara algunas estructuras de
datos que
abarcan una sección de almacenamiento
temporal para transferencia de información entre terminales y procesos,
una sección para almacenamiento de
descriptores de archivos y una variable que indica la cantidad de
memoria
principal.
A continuación, el Kernel inicializa un proceso
especial, llamado proceso 0. En
general, los procesos se crean mediante una llamada a una rutina
del sistema (fork), que funciona por un mecanismo de
duplicación de procesos. Sin embargo, esto no es
suficiente para crear el primero de ellos, por lo que el Kernel
asigna una estructura de
datos y establece apuntadores a una sección especial
de la memoria, llamada
tabla de procesos, que contendrá los descriptores de cada
uno de los procesos existentes en el sistema.
Después de haber creado el proceso 0, se hace una
copia del mismo, con lo que se crea el proceso 1; éste muy
pronto se encargará de "dar vida" al sistema completo,
mediante la activación de otros procesos que
también forman parte del núcleo. Es decir, se
inicia una cadena de activaciones de procesos, entre los cuales
destaca el conocido como despachador, o scheduler, que es el
responsable de decidir cuál proceso se ejecutará y
cuáles van a entrar o salir de la memoria central.
A partir de ese momento se conoce el número 1 como proceso
de inicialización del sistema, init.
El proceso init es el responsable de establecer la
estructura de
procesos en Unix.
Normalmente, es capaz de crear al menos dos estructuras
distintas de procesos: el modo monousuario y el multiusuario.
Comienza activando el intérprete del lenguaje de
control (Shell) en la terminal principal, o consola, del sistema
y proporcionándole privilegios de "superusuario". En la
modalidad de un solo usuario la consola permite iniciar una
primera sesión, con privilegios especiales, e impide que
las otras líneas de comunicación acepten iniciar sesiones
nuevas. Esta modalidad se usa con frecuencia para revisar y
reparar sistemas de
archivos, realizar pruebas de
funciones
básicas del sistema y para otras actividades que requieren
uso exclusivo de la
computadora.
Init crea otro proceso, que espera pacientemente a que
alguien entre en sesión en alguna línea de comunicación. Cuando esto sucede, realiza
ajustes en el protocolo de la
línea y ejecuta el programa login,
que se encarga de atender inicialmente a los nuevos usuarios. Si
la clave del usuario, y la contraseña proporcionadas son
las correctas, entonces entra en operación el programa Shell,
que en lo sucesivo se encargará de la atención
normal del usuario que se dio de alta en esa terminal.
A partir de ese momento el responsable de atender al
usuario en esa terminal es el intérprete Shell.
Cuando se desea terminar la sesión hay que
desconectarse de Shell (y, por lo tanto, de Unix), mediante una
secuencia especial de teclas (usualmente. < CTL > – D). A
partir de ese momento la terminal queda disponible para atender a
un nuevo usuario.
Administración de Archivos y
Directorios
El sistema de archivos de Unix; esta basado en un
modelo
arborescente y recursivo, en el cual los nodos pueden ser tanto
archivos como directorios, y estos últimos pueden contener
a su vez directorios o subdirectorios. Debido a esta
filosofía, se maneja al sistema con muy pocas
órdenes, que permiten una gran gama de posibilidades. Todo
archivo de
Unix está controlado por múltiples niveles de
protección, que especifican los permisos de acceso al
mismo. La diferencia que existe entre un archivo de
datos, un
programa, un manejador de entrada/salida o una instrucción
ejecutable se refleja en estos parámetros, de modo que el
sistema operativo
adquiere características de coherencia y elegancia
que lo distinguen.
La raíz del sistema de archivos (conocida como
root ) se denota con el símbolo "/", y de ahí se
desprende un conjunto de directorios que contienen todos los
archivos del sistema de cómputo. Cada directorio, a su
vez, funciona como la subraíz de un nuevo árbol que
depende de él y que también puede estar formado por
directorios o subdirectorios y archivos. Un archivo siempre
ocupará el nivel más bajo dentro del árbol,
porque de un archivo no pueden
depender otros; si así fuera, sería un directorio.
Es decir, los archivos son como las hojas del
árbol.
Se define en forma unívoca el nombre de todo
archivo (o
directorio) mediante lo que se conoce como su trayectoria (path
name): es decir, el conjunto completo de directorios, a partir de
root (/), por los que hay que pasar para poder llegar
al directorio o archivo deseado. Cada nombre se separa de los
otros con el símbolo /, aunque tan sólo el primero
de ellos se refiere a la raíz.
Por ejemplo, el archivo
u/gerencia/abril94l/carta2
tiene toda esta trayectoria como nombre absoluto, pero
se llama gerencia/abril94l/carta2, sin 1ra diagonal
inicial, si se observa desde el directorio /u. Para los usuarios
que están normalmente en el directorio /u/gerencia, el
archivo se llama abril94l/carta2. Así, también
puede existir otro archivo llamado carta2, pero dentro de
algún otro directorio y en caso de ser necesario se
emplearía el nombre de la trayectoria (completa o en
partes, de derecha a izquierda) para distinguirlos. Unix ofece
medios muy
sencillos para colocarse en diferentes puntos del árbol
que forma el sistema de archivos, que para el ejemplo anterior
podría ser el siguiente:
Como se dijo antes, desde el punto de vista del
directorio abril94, que a su vez pertenece al directorio gerencia del
directorio /u, basta con el nombre carta2 para apuntar al archivo
en cuestión.
En esta forma se maneja el sistema completo de archivos
y se dispone de un conjunto de órdenes de Shell
(además de múltiples variantes) para hacer diversas
manipulaciones, como crear directorios, moverse dentro del
sistema de archivos, copiarlos, etcétera.
Unix incluye, además, múltiples esquemas
para crear, editar y procesar documentos.
Existen varios tipos de editores, formadores de textos,
macroprocesadores para textos, formadores de tablas,
preprocesadores de expresiones matemáticas y un gran número de
ayudas y utilerías diversas, que se mencionan más
adelante.
A continuación se describe el modo de
funcionamiento de Unix, con base en un modelo de
estudio de sistemas
operativos que lo divide en "capas" jerárquicas para
su mejor comprensión.
Manejo de archivos y de información
Como ya se describió, la estructura
básica del sistema de archivos es jerárquica, lo
que significa que los archivos están almacenados en varios
niveles. Se puede tener acceso a cualquier archivo mediante su
trayectoria, que especifica su posición absoluta en la
jerarquía, y los usuarios pueden cambiar su directorio
actual a la posición deseada. Existe también un
mecanismo de protección para evitar accesos no
autorizados. Los directorios contienen información para cada archivo, que consiste
en su nombre y en un número que el Kernel utiliza para
manejar la estructura
interna del sistema de archivos, conocido como el nodo-i. Hay un
nodo-i para cada archivo, que contiene información de su directorio en el disco,
su longitud, los modos y las fechas de acceso, el autor, etc.
Existe, además, una tabla de descriptores de archivo, que
es una estructura de
datos residente en el disco magnético, a la que se
tiene acceso mediante el sistema mencionado de E/S por
bloques.
El control del espacio libre en el disco se mantiene
mediante una lista ligada de bloques disponibles. Cada bloque
contiene la dirección en disco del siguiente bloque en
la cadena. El espacio restante contiene las direcciones de
grupos de
bloques del disco que se encuentren libres. De esta forma, con
una operación de E/S, el sistema obtiene un conjunto de
bloques libres y un apuntador para conseguir
más.
Las operaciones de
E/S en archivos se llevan a cabo con la ayuda de la
correspondiente entrada del nodo-i en la tabla de archivos del
sistema. El usuario normalmente desconoce los nodos-i porque las
referencias se hacen por el nombre simbólico de la
trayectoria. Los procesos emplean internamente funciones
primitivas (llamadas al sistema) para tener acceso a los
archivos; las más comunes son open, creat, read, write,
seek, close y unlink, aunque sólo son empleadas por los
programadores, no por los usuarios finales del
sistema.
Toda esta estructura
física se
maneja "desde afuera" mediante la filosofía
jerárquica de archivos y directorios ya mencionada, y en
forma totalmente transparente para el usuario. Además,
desde el punto de vista del sistema
operativo, un archivo es muy parecido a un
dispositivo.
Las ventajas de tratar a los dispositivos de E/S en
forma similar a los archivos normales son múltiples: un
archivo y un dispositivo de E/S se tornan muy parecidos; los
nombres de los archivos y de los dispositivos tienen la misma
sintaxis y significado, así que a un programa que espera
un nombre de archivo como parámetro puede dársele
un nombre de dispositivo (con esto se logra interacción
rápida y fácil entre procesos de alto
nivel).
El sistema Unix ofrece varios niveles de
protección para el sistema de archivos, que consisten en
asignar a cada archivo el número único de
identificación de su dueño, junto con nueve bits de
protección, que especifican permisos de lectura,
escritura y
ejecución para el propietario, para otros miembros de su
grupo
(definido por el administrador del
sistema) y para el resto de los usuarios. Antes de cualquier
acceso se verifica su validez consultando estos bits, que residen
en el nodo-i de todo archivo. Además, existen otros tres
bits que se emplean para manejos especiales, relacionados con la
clave del superusuario.
Otra característica de Unix es que no requiere
que el conjunto de sistemas de
archivos resida en un mismo dispositivo.
Es posible definir uno o varios sistemas
"desmontables", que residen físicamente en diversas
unidades de disco. Existe una orden (mkfs) que permite crear un
sistema de archivos adicional, y una llamada al sistema (mount)
con la que se añade (y otra con la que se desmonta) uno de
ellos al sistema de archivos global.
EI control de las impresoras de
una computadora
que funciona con el sistema operativo Unix consiste en un
subsistema (SPOOL) que se encarga de coordinar los pedidos de
impresión de múltiples usuarios. Existe un proceso
de Kernel que en forma periódica revise las colas de
servicio de
las impresoras
para detectar la existencia de pedidos e iniciar entonces las
tareas de impresión. Este tipo de procesos, que son
activados en forma periódica por el núcleo del
sistema operativo, reciben en Unix el nombre de daemons
(duendes), tal vez porque se despiertan y aparecen sin previo
aviso. Otros se encargan de activar procesos en tiempos
previamente determinados por el usuario, o de escribir
periódicamente los contenidos de los buffers de memoria en el
disco magnético.
Procesos. Manejo del Procesador
En Unix se ejecutan programas en un
medio llamado "proceso de usuario". Cuando se requiere una
función del Kernel, el proceso de usuario hace una llamada
especial al sistema y entonces el control pasa temporalmente al
núcleo. Para esto se requiere de un conjunto de elementos
de uso interno, que se mencionan a
continuación.
Se conoce como imagen a una
especie de fotografía
del ambiente de
ejecución de un proceso, que incluye una
descripción de la memoria, valores de
registros
generales, status de archivos abiertos, el directorio actual,
etcétera. Una imagen es
el estado
actual de una computadora
virtual, dedicada a un proceso en particular.
Un proceso se define como la ejecución de una
imagen.
Mientras el procesador
ejecuta un proceso, la imagen debe
residir en la memoria principal; durante la ejecución de
otros procesos permanece primera en la memoria principal a
menús que la aparición de un proceso activo de
mayor prioridad la obligue a ser copiada al disco, como ya se
dijo.
Un proceso puede encontrarse en uno de varios estados:
en ejecución; listo para ejecutar, o en espera.
Cuando se invoca una función del sistema, el
proceso de usuario llama al Kernel como subrutina. Hay un
cambio de
ambientes y, como resultado, se tiene un proceso del sistema.
Estos dos procesos son dos fases del mismo original, que nunca se
ejecutan en forma simultánea.
Existe una tabla de procesos que contiene una entrada
por cada uno de ellos con los datos que
requiere el sistema:
identificación, direcciones de los segmentos que
emplea en la memoria, información que necesita el
scheduler y otros. la entrada de la tabla de procesos se asigna
cuando se crea el proceso y se libera cuando éste
termina.
Para crear un proceso se requiere la
inicialización de una entrada en la tabla, así como
la creación de segmentos de texto y de
datos. Además, es necesario modificar la tabla cuando
cambia el estado del
proceso o cuando recibe un mensaje de otro (para
sincronización, por ejemplo). Cuando un proceso termina,
su entrada en la tabla se libera y queda otro disponible para que
otro nuevo la utilice.
En el sistema operativo Unix los procesos pueden
comunicarse internamente entre sí, mediante el
envío de mensajes o señales. El mecanismo conocido
como interconexión (pipe) crea un canal entre dos procesos
mediante una llamada a una rutina del Kernel, y se emplea tanto
para pasar datos unidireccionalmente entre las imágenes
de ambos, como para sincronizarlos, ya que si un proceso intenta
escribir en un pipe ocupado, debe esperar a que el receptor lea
los datos pendientes. Lo mismo ocurre en el caso de una lectura de
datos inexistentes: el proceso que intenta leer debe esperar a
que el proceso productor deposite los datos en el canal de
intercomunicación.
Entre las diferentes llamadas al sistema para el manejo
de procesos que existen en Unix están las siguientes,
algunas de las cuales ya han sido mencionadas: fork (sacar una
copia a un proceso); exec (cambiar la identidad de
un proceso); kill (enviar una señal a un proceso); signal
(especificar la acción por ejecutar cuando se recibe una
señal de otro proceso), y exit (terminar un
proceso).
Dentro de las tareas del manejo del procesador destaca
la asignación dinámica (scheduling), que en Unix resuelve
el scheduler mediante un mecanismo de prioridades. Cada proceso
tiene asignada una prioridad; las prioridades de los procesos de
usuario son menores que la más pequeña de un
proceso del sistema.
El "motor" que
mantiene en movimiento un
esquema de multiprogramación es, por un lado, el conjunto
de interrupciones que genera el desempeño de los procesos
y, por otro, los constantes recordatorios que hace el reloj del
procesador para indicar que se terminó la fracción
de tiempo
dedicada a cada proceso.
En el sistema Unix, las interrupciones son causadas por
lo que se conoce como eventos, entre
los cuales se consideran: la ejecución de una tarea de
entrada/salida; la terminación de los procesos
dependientes de otro; la terminación de la fracción
de tiempo
asignada a un proceso, y la recepción de una señal
desde otro proceso.
En un sistema de tiempo compartido
se divide el tiempo en un
determinado número de intervalos o fracciones y se asigna
cada una de ellas a un proceso. Además Unix toma en
consideración que hay procesos en espera de una
operación de E/S y que ya no pueden aprovechar su
fracción. Para asegurar una distribución adecuada del procesador entre
los procesos se calculan dinámicamente las prioridades de
estos últimos, con el fin de determinar cuál
será el proceso que se ejecutará cuando se suspenda
el proceso activo actual.
Manejo De Memoria
Dependiendo de la computadora
en la que se ejecute, Unix utiliza dos técnicas de manejo
de memoria: swapping y memoria
virtual.
Lo estándar en Unix es un sistema de intercambio
de segmentos de un proceso entre memoria principal y memoria
secundaria, llamado swapping lo que significa que se debe mover
la imagen de un
proceso al disco si éste excede la capacidad de la memoria
principal, y copiar el proceso completo a memoria secundaria. Es
decir, durante su ejecución, los procesos son cambiados de
y hacia memoria secundaria conforme se requiera.
Si un proceso necesita crecer, pide más memoria
al sistema operativo y se le da una nueva sección, lo
suficientemente grande para acomodarlo. Entonces, se copia el
contenido de la sección usada al área nueva, se
libera la sección antigua y se actualizan las tablas de
descriptores de procesos. Si no hay suficiente memoria en el
momento de la expansión, el proceso se bloquea
temporalmente y se le asigna espacio en memoria secundaria. Se
copia a disco y, posteriormente, cuando se tiene el espacio
adecuado – lo cual sucede normalmente en algunos segundos – se
devuelve a memoria principal.
Está claro que el proceso que se encarga de los
intercambios entre memoria y disco (llamado swapper) debe ser
especial y jamás podrá perder su posición
privilegiada en la memoria central. El Kernel se encarga de que
nadie intente siquiera interrumpir este proceso, del cual
dependen todos los demás. Este es el proceso 0 mencionado
antes. Cuando se decide traer a la memoria principal un proceso
en estado de
"listo para ejecutar", se le asigna memoria y se copian
allí sus segmentos. Entonces, el proceso cargado compite
por el procesador con todos los demás procesos cargados.
Si no hay suficiente memoria, el proceso de intercambio examine
la tabla de procesos para determinar cuál puede ser
interrumpido y llevado al disco.
Hay una pregunta que surge entonces es
¿cuál de los posibles procesos que están
cargados será desactivado y cambiado a memoria secundaria?
Los procesos que se eligen primero son aquellos que están
esperando operaciones
lentas (E/S), o que llevan cierto tiempo sin haberse movido al
disco. La idea es tratar de repartir en forma equitativa las
oportunidades de ejecución entre todos los procesos,
tomando en cuenta sus historias recientes y sus patrones de
ejecución.
Otra pregunta es ¿cuál de todos los
procesos que están en el disco será traído a
memoria principal?. La decisión se toma con base en el
tiempo de residencia en memoria secundaria. El proceso más
antiguo es el que se llama primero, con una pequeña
penalización para los grandes.
Cuando Unix opera en máquinas más grandes,
suele disponer de manejo de memoria de paginación por
demanda. En
algunos sistemas el
tamaño de la página en Unix es de 512 bytes; en
otros, de 1024. Para reemplazo se usa un algoritmo que
mantiene en memoria las páginas empleadas más
recientemente.
Un sistema de paginación por demanda ofrece
muchas ventajas en cuanto a flexibilidad y agilidad en la
atención concurrente de múltiples procesos y
proporciona, además, memoria
virtual, es decir, la capacidad de trabajar con procesos
mayores que el de la memoria central. Estos esquemas son bastante
complejos y requieren del apoyo de hardware
especializado.
Manejo de entradas y salidas
El sistema de entrada/salida se divide en dos sistemas
complementarios: el estructurado por bloques y el estructurado
por caracteres. El primero se usa para manejar cintas y discos
magnéticos, y emplea bloques de tamaño fijo (512 o
1024 bytes) para leer o escribir. El segundo se utiliza para
atender a las terminales, líneas de comunicación e
impresoras, y
funciona byte por byte.
En general, el sistema Unix emplea programas especiales
(escritos en C) conocidos como manejadores (drivers) para atender
a cada familia de
dispositivos de E/S. Los procesos se comunican con los
dispositivos mediante llamadas a su manejador. Además,
desde el punto de vista de los procesos, los manejadores aparecen
como si fueran archivos en los que se lee o escribe; con esto se
logra gran homogeneidad y elegancia en el diseño.
Cada dispositivo se estructura
internamente mediante descriptores llamados número mayor,
número menor y clase (de bloque o de caracteres). Para
cada clase hay un conjunto de entradas, en una tabla, que aporta
a los manejadores de los dispositivos. El número mayor se
usa para asignar manejador, correspondiente a una familia de
dispositivos; el menor pasa al manejador como un argumento, y
éste lo emplea para tener acceso a uno de varios
dispositivos físicos semejantes.
Las rutinas que el sistema emplea para ejecutar operaciones de
E/S están diseñadas para eliminar las diferencias
entre los dispositivos y los tipos de acceso. No existe
distinción entre acceso aleatorio y secuencial, ni hay un
tamaño de registro
lógico impuesto por el
sistema. El tamaño de un archivo ordinario está
determinado por el número de bytes escritos en él;
no es necesario predeterminar el tamaño de un
archivo.
El sistema mantiene una lista de áreas de
almacenamiento
temporal (buffers), asignadas a los dispositivos de bloques. El
Kernel usa estos buffers con el objeto de reducir el
tráfico de E/S. Cuando un programa solicita una
transferencia, se busca primero en los buffers internos para ver
si el bloque que se requiere ya se encuentra en la memoria
principal (como resultado de una operación de lectura
anterior). Si es así, entonces no será necesario
realizar la operación física de entrada o
salida.
Existe todo un mecanismo de manipulación interna
de buffers (y otro de manejo de listas de bytes), necesario para
controlar el flujo de datos entre los dispositivos de bloques (y
de caracteres) y los programas que los requieren.
Por último, y debido a que los manejadores de los
dispositivos son programas escritos en lenguaje C, es
relativamente fácil reconfigurar el sistema para ampliar o
eliminar dispositivos de E/S en la
computadora, así como para incluir tipos
nuevos.
Lenguaje de control del sistema
operativo
Entre los rasgos distintivos de Unix está
el lenguaje de
control que emplea, llamado Shell. Es importante analizar dos
funciones
más de Shell, llamadas redireccionamiento e
Interconexión.
Asociado con cada proceso hay un conjunto de
descriptores de archivo numerados 0, I y 2, que se utilizan para
todas las transacciones entre los procesos y el sistema
operativo. El descriptor de archivo 0 se conoce como la entrada
estándar; el descriptor de archivo 1, como la salida
estándar, y el descriptor 2, como el error
estándar. En general, todos están asociados con la
terminal de vídeo, pero, debido a que inicialmente son
establecidos por Shell, es posible reasignarlos.
Una parte de la orden que comience con el símbolo
? se considera como el nombre del archivo que será abierto
por Shell y que se asociará con la entrada
estándar; en su ausencia, la entrada estándar se
asigna a la terminal. En forma similar, un archivo cuyo nombre
está precedido por el símbolo > recibe la salida
estándar de las operaciones.
Cuando Shell interpreta la orden
califica < examen > resulta
llama a ejecución al programa califica (que ya
debe estar compilado y listo para ejecutar) y detecta la
existencia de un archivo que toma el lugar de la entrada
estándar y de otro que reemplaza a la salida
estándar. Después, pasa como datos de lectura los
contenidos del archivo examen recién abierto (que debe
existir previamente) al programa ejecutable. Conforme el programa
produce datos como salida, éstos se guardan en el archivo
resulta que Shell crea en ese momento.
En la teoría
de lenguajes formales desempeñan un importante papel las
gramáticas llamadas de tipo 3 (también conocidas
como regulares), que tienen múltiples aplicaciones en el
manejo de lenguajes. Existen unas construcciones gramaticales
conocidas como expresiones regulares, con las que se puede hacer
referencia a un conjunto ilimitado de nombres con estructura
lexicográfica similar; esto lo aprovecha Shell para dar al
usuario facilidades expresivas adicionales en el manejo de los
nombres de los archivos. Así, por ejemplo, el nombre
carta * se
refiere a todos los archivos que comiencen con el prefijo
carta* y que
sean seguidos por cualquier subcadena, incluyendo la cadena
vacía; por ello, si se incluye el nombre carta* en alguna
orden, Shell la aplicará a los archivos carta, carta1,
carta2 y cualquier otro que cumpla con esa especificación
abreviada. En general, en lugares donde se emplea un nombre o una
trayectoria, Shell permite utilizar una expresión regular
que sirve como abreviatura para toda una familia de ellos,
y automáticamente repite el pedido de atención para
los componentes. Existen además otros caracteres
especiales que Shell reconoce y emplea para el manejo de
expresiones regulares, lo que proporciona al lenguaje de
control de Unix mayor potencia y
capacidad expresiva.
En Unix existe también la posibilidad de ejecutar
programas sin tener que atenderlos en forma interactiva, sino
simulando paralelismo (es decir, atender de manera concurrente
varios procesos de un mismo usuario). Esto se logra agregando el
símbolo & al final de la línea en la que se
escribe la orden de ejecución. Como resultado, Shell no
espera que el proceso "hijo'' termine de ejecutar (como
haría normalmente), sino que regresa a atender al usuario
inmediatamente después de haber creado el proceso
asincrónico, simulando en esta forma el procesamiento por
lotes ( batch ) Para cada uno de estos procesos Shell
proporciona, además, el número de
identificación, por lo que si fuera necesario el usuario
podría cancelarlo posteriormente, o averiguar el avance de
la ejecución.
La comunicación interna entre procesos (es decir,
el envío de mensajes con los que los diversos procesos se
sincronizan y coordinan) ocurre mediante el mecanismo de
interconexiones (pipes) ya mencionado, que conecta la salida
estándar de un programa a la entrada estándar de
otro, como si fuera un conducto con dos extremos, cada uno de los
cuales está conectado a su vez a un proceso distinto.
Desde Shell puede emplearse este mecanismo con el símbolo
| en la línea donde se escribe la orden de
ejecución.
Así en el ejemplo:
(califica < tarea | sorte > lista)
&
se emplean las características de
interconexión, redireccionamiento y asincronía de
procesos para lograr resultados difíciles de obtener en
otros sistemas
operativos. Aquí se pide que, en forma
asincrónica (es decir, dejando que la terminal siga
disponible para atender otras tareas del mismo usuario), se
ejecute el programa califica para que lea los datos que requiere
del archivo tareas; al terminar, se conectará con el
proceso sort (es decir, pasará los resultados intermedios)
para que continúe el procesamiento y se arreglen los
resultados en orden alfabético; al final de todo esto, los
resultados quedarán en el archivo lista.
Con esta otra orden, por ejemplo, se busca obtener todos
los renglones que contengan las palabras "contrato" o
"empleado" en los archivos en disco cuyos nombres comiencen con
la letra "E" (lo cual se denota mediante una expresión
regular). Para lograrlo, se hace uso de una función
llamada egrep, especial para el manejo de patrones y
combinaciones de expresiones regulares dentro de los
archivos:
egrep-n 'contrato'
'empleado' E *
Los resultados aparecen así:
Emple1: 5: en caso de que un empleado decide hacer uso
de la facilidad,
Emple1:7: y el contrato
así lo considere las obligaciones
de la
Emple2:9: Cláusula II: El contrato
colectivo de trabajo
Emple2:15: Fracción llI: El empleado
tendrá derecho, de acuerdo con lo
El tercer renglón, por ejemplo, muestra el noveno
renglón del archivo Emple2, que contiene una de las
palabras buscadas.
Como Unix fue diseñado para servir de entorno en
las labores de diseño
y producción de programas, ofrece –
además de su filosofía misma – un rico conjunto de
herramientas
para la creación de sistemas complejos, entre las que
destaca el subsistema make. Este último ofrece una especie
de lenguaje muy sencillo, con el cual el programador describe las
relaciones estructurales entre los módulos que configuran
un sistema completo, para que de ahí en adelante make se
encargue de mantener el sistema siempre al día. Es decir,
si se modifica algún módulo, se reemplaza o se
añade otro, las compilaciones individuales, así
como las cargas y ligas a que haya lugar, serán realizadas
en forma automática, por esta herramienta. Con una sola
orden, entonces, es posible efectuar decenas de compilaciones y
ligas predefinidas entre módulos, y asegurarse de que en
todo momento se tiene la última versión de un
sistema, ya que también se lleva cuenta automática
de las fechas de creación, modificación y
compilación de los diversos módulos. De esta
manera, se convierte en una herramienta casi indispensable al
desarrollar aplicaciones que requieren decenas de programas que
interactúan entre sí o que mantienen relaciones
jerárquicas.
Otras herramientas
interesantes son ar, diseñado para crear y mantener
bibliotecas de
programas (que serán luego utilizadas por otros programas
para efectuar las funciones ya definidas sin tener que duplicar
el código); awk, un lenguaje para reconocimiento de
patrones y expresiones regulares (es decir, generadas por una
gramática regular o de tipo 3), útil
para extraer información de archivos en forma selectiva;
lex, un generador de analizadores lexicográfico, y yacc,
un compilador de compiladores.
Estos dos últimos se emplean como herramientas
en la creación de compiladores y
procesadores de
lenguajes.
La lista complete de funciones, órdenes de
subsistemas que forman parte de las utilerías del sistema
operativo Unix es realmente grande, e incluye más de un
centenar, que se pueden agrupar en los siguientes
rubros:
Compiladores de compiladores.
Ejecución de programas.
Facilidades de comunicaciones.
Funciones para control de status.
Funciones para control de usuarios.
Funciones para impresión.
Herramientas de desarrollo de
programación.
Lenguaje C, funciones y bibliotecas
asociados.
Macroprocesamiento.
Manejo de directorios y archivos.
Manejo de gráficas.
Manejo de información.
Manejo de terminales.
Mantenimiento y respaldos.
Otros lenguajes algorítmicos
integrados.
Preparación de documentos.
Autor:
Martinoli Diego