apunteIC 2023 08 16
apunteIC 2023 08 16
apunteIC 2023 08 16
Facultad de Informática
Introducción a la computación
Apunte de la materia
Versión 2.0 - Revisión IC 2023
1. Historia de la Computación 1
1.1. Antecedentes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.2. Primera Generación (1938-1950) . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.3. Segunda Generación (1951-1964) . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.4. Tercera Generación (1965-1971) . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.5. Cuarta Generación (1971-actualidad) . . . . . . . . . . . . . . . . . . . . . . . . . 7
2. Sistemas de Numeración 9
2.1. Introducción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.2. Sistema posicional y base de un sistema de numeración . . . . . . . . . . . . . . . 10
2.2.1. Expresión General . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.3. Conversión de base . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.3.1. Conversión de base 10 a otras bases . . . . . . . . . . . . . . . . . . . . . 11
2.3.2. Conversión de otras bases a base 10 . . . . . . . . . . . . . . . . . . . . . 12
2.3.3. Conversión entre bases arbitrarias . . . . . . . . . . . . . . . . . . . . . . 13
2.3.4. Conversión entre sistemas binario y octal o hexadecimal . . . . . . . . . . 13
3. Unidades de Información 15
3.1. ¿Qué es la Información? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
3.2. El Bit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
3.2.1. El viaje de un bit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
3.3. El Byte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
3.4. Sistemas de medición . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
3.4.1. Sistema Internacional . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
3.4.2. Sistema de Prefijos Binarios . . . . . . . . . . . . . . . . . . . . . . . . . . 17
3.4.3. ¿Por qué dos sistemas? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
iii
iv ÍNDICE GENERAL
6. Organización de Computadoras 47
6.1. Componentes de una computadora . . . . . . . . . . . . . . . . . . . . . . . . . . 47
6.2. Arquitectura de von Neumann . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
6.3. ISA: Conjunto de Instrucciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
ÍNDICE GENERAL v
8. El Software 59
8.1. Lenguajes de bajo nivel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
8.1.1. Lenguaje máquina . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
8.1.2. Lenguaje ensamblador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
8.2. Lenguajes de alto nivel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
8.2.1. Compiladores e intérpretes . . . . . . . . . . . . . . . . . . . . . . . . . . 63
8.2.2. Fases del ciclo de compilación . . . . . . . . . . . . . . . . . . . . . . . . . 64
9. Sistemas Operativos 67
9.1. Evolución del software de base . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
9.1.1. Open Shop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
9.1.2. Sistemas Batch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
9.1.3. Sistemas Multiprogramados . . . . . . . . . . . . . . . . . . . . . . . . . . 67
9.1.4. Sistemas de Tiempo Compartido . . . . . . . . . . . . . . . . . . . . . . . 67
9.1.5. Computación personal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
9.1.6. Preguntas de repaso para el coloquio o el final . . . . . . . . . . . . . . . 68
9.2. Componentes del SO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
9.3. Kernel del SO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
9.3.1. Funciones del Kernel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
9.3.2. Modo dual de operación . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
vi ÍNDICE GENERAL
10.Redes de computadoras 85
10.1. Clasificación de las redes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
10.2. Componentes de Hardware . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
10.2.1. Hosts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
10.2.2. Enlaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
10.2.3. Nodos intermedios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
10.2.4. Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
10.3. Componentes de Software . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
10.3.1. Aplicaciones de Red . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
10.3.2. Protocolos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
10.3.3. Modelo de Internet de 5 capas . . . . . . . . . . . . . . . . . . . . . . . . 91
10.4. Direccionamiento en Internet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
10.4.1. Direcciones de red . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
10.4.2. Paquetes IP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
10.4.3. Ruteo o encaminamiento . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
10.5. Servicio de Nombres de Dominio (DNS) . . . . . . . . . . . . . . . . . . . . . . . 93
10.5.1. Jerarquı́a de nombres de dominio . . . . . . . . . . . . . . . . . . . . . . . 93
10.5.2. Resolución de nombres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
10.6. Administración de redes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
10.6.1. Comando ping . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
10.6.2. Comando traceroute . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
Índice de figuras
vii
viii ÍNDICE DE FIGURAS
9.2. Primer proyecto que implementó un sistema de tiempo compartido (1957) IBM
704 modificado. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
Historia de la Computación
1.1. Antecedentes
Las computadoras actuales tienen una genealogı́a muy extensa. En el periodo posterior a la
Edad Media y anterior a la Edad Moderna, se sentaron las bases para la búsqueda de máquinas
de computación más sofisticadas. Unos cuantos inventores comenzaron a experimentar con la
tecnologı́a de los engranajes. Entre ellos estaban Blaise Pascal (1623–1662) en Francia, Gottfried
Wilhelm Leibniz (1646–1716) en Alemania y Charles Babbage (1792–1871) en Inglaterra. Estas
máquinas representaban los datos mediante posicionamiento con engranajes, introduciéndose los
datos mecánicamente por el procedimiento de establecer las posiciones iniciales de esos engrana-
jes. En las máquinas de Pascal y Leibniz, la salida se conseguı́a observando las posiciones finales
de los engranajes. Babbage, por su parte, concibió máquinas que imprimı́an los resultados de
los cálculos en papel, con el fin de poder eliminar la posibilidad de que se produjeran errores de
transcripción.
Por lo que respecta a la capacidad de seguir un algoritmo, podemos ver una cierta progresión
en la flexibilidad de estas máquinas. La máquina de Pascal se construyó para realizar únicamente
sumas. En consecuencia, la secuencia apropiada de pasos estaba integrada dentro de la propia
estructura de la máquina. De forma similar, la maquina de Leibniz tenı́a los algoritmos firme-
mente integrados en su arquitectura, aunque ofrecı́a diversas operaciones aritméticas entre las
que el operador podrı́a seleccionar una.
La máquina diferencial de Babbage (de la que solo se construyó
un modelo de demostración) podı́a modificarse para realizar diversos
cálculos, pero su máquina analı́tica (para cuya construcción nunca
consiguió financiación) estaba diseñada para leer las instrucciones en
forma de agujeros realizados en una tarjeta de cartón. Por tanto, la
máquina analı́tica de Babbage era programable. De hecho, se conside-
ra a Augusta Ada Byron (Ada Lovelace), que publicó un artı́culo en el
que ilustraba cómo podrı́a programarse la máquina analı́tica de Bab-
bage para realizar diversos cálculos, como la primera programadora
del mundo.
Herman Hollerith (1860–1929) también aplicó el concepto de re-
presentar la información mediante agujeros en tarjetas de cartón para Charles Babbage
acelerar el proceso de tabulación de resultados en el censo de Estados (1792–1871)
Unidos de 189 (fue este trabajo de Hollerith el que condujo a la crea-
ción de la empresa IBM). Dichas tarjetas terminaron siendo conocidas
con el nombre de tarjetas perforadas y sobrevivieron como método popular de comunicación
con las computadoras hasta bien avanzada la década de 1970.
1
2 CAPÍTULO 1. HISTORIA DE LA COMPUTACIÓN
Tarjeta Perforada
Colossus (1943,1944)
Clementina
¿Qué pasaba en nuestro paı́s durante estas épocas? La actividad de la computación aquı́ no
habı́a comenzado. Recién a principios de los años 60 la universidad argentina decidió hacer una
importante inversión, que fue la compra de una computadora de primera generación, bautizada
aquı́ Clementina.
4 CAPÍTULO 1. HISTORIA DE LA COMPUTACIÓN
Colossus (1943,1944)
ENIAC (1945)
1.3. SEGUNDA GENERACIÓN (1951-1964) 5
ENIAC (1945)
En 1948 se descrubre que combinando elementos que eran vecinos en la tabla periódica,
se creaban nuevos materiales con un desbalance de electrones; y que de esta manera se podı́a
controlar el sentido de las corrientes eléctricas que atravesaban esos materiales. Ası́ fue inventado
un componente electrónico revolucionario, el transistor, que era básicamente un triodo de
estado sólido, es decir, podı́a cumplir el mismo papel en un circuito que la válvula termoiónica
de tres electrodos, pero era construido de una forma completamente diferente. Esto significa que
las mismas funciones lógicas de los interruptores, que en las computadoras de primera generación
eran cumplidas por las válvulas termoiónicas, podı́an ser resueltas con dispositivos mucho más
pequeños, de mucho menor consumo, con tiempos de reacción mucho menores y mucho más
confiables.
Con estos desarrollos, las máquinas de la década de 1940, que
tenı́an el tamaño de una habitación, se redujeron a lo largo de las
décadas siguientes hasta el tamaño de un armario. Algunas de las de-
sarrolladas en esta época recibieron el nombre de minicomputado-
ras. El PDP-1 fue uno de los primeros computadores que pudieron ser
accedidos masivamente por los estudiantes de computación. Tenı́a un
sistema de tiempo compartido (time-sharing) que hacı́a posible
la utilización de la máquina por varios usuarios a la vez. Tenı́a 144 KB
de memoria principal y ejecutaba 100.000 instrucciones por segundo.
PDP-1 (1959)
El microprocesador desarrollado por Intel reunió la mayor parte de las funciones de las
computadoras en un solo microchip. La existencia del microprocesador favoreció la creación de
una industria de las computadoras personales. En 1982 IBM propuso el PC (Personal Com-
puter), un computador personal o microcomputador del cual descienden la mayorı́a de
las computadoras domésticas y de oficina que se usan hoy. Al contrario que las computadoras
de hasta entonces, construidas con procedimientos y componentes propios del fabricante, y a
1.5. CUARTA GENERACIÓN (1971-ACTUALIDAD) 7
Sistemas de Numeración
2.1. Introducción
9
10 CAPÍTULO 2. SISTEMAS DE NUMERACIÓN
Numerales Números
2 × 1000 + 0 × 100 + 1 × 10 + 7 × 1
2.3. CONVERSIÓN DE BASE 11
Los dı́gitos 2, 0, 1 y 7 se multiplican, respectivamente, por 103 , 102 , 101 y 100 , que son poten-
cias de la base 10. Este numeral designa al número 2017 porque esta cuenta, efectivamente,
da 2017.
Si el número está expresado en otra base, la cuenta debe hacerse con potencias de esa otra
base. Si hablamos de 2017(8) , entonces las cifras 2, 0, 1 y 7 multiplican a 83 , 82 , 81 y 80 . Este
numeral designa al número 1039 porque esta cuenta, efectivamente, da 1039.
La forma de calcular el valor de un numeral en una base b genérica, es igual a la forma vista
anteriormente, sólo que con potencias de la base correspondiente. Las cifras de un numeral
escrito en cualquier base son los factores por los cuales hay que multiplicar las sucesivas
potencias de la base para saber a qué número nos estamos refiriendo.
Veamos la expresión general que nos permite escribir un número n (no negativo) en una
base b:
n = xk × bk + . . . + x2 × b2 + x1 × b1 + x0 × b0
k
X
n= xi × bi
i=0
El procedimiento para convertir un número escrito en base 10 a cualquier otra base (llamémos-
la base destino) es siempre el mismo y se basa en la división entera (sin decimales). Procedi-
miento:
Finalmente escribimos los dı́gitos de nuestro número convertido usando el último cocien-
te y todos los restos en orden inverso a como aparecieron. Ésta es la expresión de
nuestro número original en la base destino.
Notemos que cada uno de los restos obtenidos es con toda seguridad menor que la base
destino, ya que, en otro caso, podrı́amos haber seguido adelante con la división entera.
Notemos también que el último cociente es también menor que la base destino, por el
mismo motivo de antes (podrı́amos haber proseguido la división).
Lo que acabamos de decir garantiza que tanto el último cociente, como todos los restos
aparecidos en el proceso, son dı́gitos válidos de un sistema en la base destino al
ser todos menores que ella.
La conversión en el sentido opuesto, de una base b cualquiera a base 10, se realiza simplemente
aplicando la Expresión General. Cada uno de los dı́gitos del número original (ahora en base b
arbitraria) es el coeficiente de alguna potencia de la base original. Esta potencia depende de la
posición de dicho dı́gito. Una vez que escribimos todos los productos de los dı́gitos originales por
las potencias de la base, hacemos la suma y nos queda el resultado: el número original convertido
a base 10.
Es de la mayor importancia cuidar de que las potencias de la base que intervienen en el cálculo
estén ordenadas y completas. Es fácil si escribimos estas potencias a partir de la derecha,
comenzando por la que tiene exponente 0, y vamos completando los términos de derecha a
izquierda hasta agotar las posiciones del número original.
10 = 1 × 8 + 0 × 4 + 1 × 2 + 0 × 1 = 1010(2)
15 = 1 × 8 + 1 × 4 + 1 × 2 + 1 × 1 = 1111(2)
Las computadoras digitales, tal como las conocemos hoy, almacenan todos sus datos en
forma de números binarios. Es muy recomendable, para la práctica de esta materia, adquirir
velocidad y seguridad en la conversión desde y hacia el sistema binario. Una manera de facilitar
esto es memorizar los valores de algunas potencias iniciales de la base 2:
2.3. CONVERSIÓN DE BASE 13
27 26 25 24 23 22 21 20
128 64 32 16 8 4 2 1
¿Qué utilidad tiene memorizar esta tabla? Que nos permite convertir mentalmente algunos
casos simples de números en sistema decimal, a base 2. Por ejemplo, veamos los pasos para
convertir el número 12 a binario:
Sumamos los números ya convertidos en binario. En este caso 1000(2) + 100(2) = 1100(2)
Hemos visto los casos de conversión entre base 10 y otras bases, en ambos sentidos. Ahora
veamos los casos donde ninguna de las bases origen o destino es la base 10. La buena noticia es
que, en general, esto ya sabemos hacerlo. Si tenemos dos bases b1 y b2 cualesquiera, ninguna
de las cuales es 10, sabiendo hacer las conversiones anteriores podemos hacer la conversión de
b1 a b2 sencillamente haciendo dos conversiones pasando por la base 10. Si queremos
convertir de b1 a b2 , convertimos primero de b1 a base 10 y luego de base 10 a b2 , aplicando
los procedimientos ya vistos. Eso es todo.
Pero en algunos casos especiales podemos aprovechar cierta relación existente entre las bases
a convertir: por ejemplo, cuando son 2 y 16 (binario y hexadecimal), o 2 y 8 (binario y octal). En
estos casos, como 16 y 8 son potencias de 2 (la otra base), podemos aplicar un truco matemático
para hacer la conversión en un solo paso y con muchı́sima facilidad. Por fortuna son estos casos
especiales los que se presentan con mayor frecuencia en nuestra disciplina. Para poder aplicar
este truco se necesita la tabla de equivalencias entre los dı́gitos de los diferentes sistemas. Si
no logramos memorizarla, conviene al menos saber reproducirla, asegurándose de saber contar
en las bases 2, 8 y 16 para reconstruir la tabla si es necesario. Pero con la práctica, se logra
memorizarla fácilmente.
14 CAPÍTULO 2. SISTEMAS DE NUMERACIÓN
El sistema octal tiene ocho dı́gitos (0 . . . 7) y cada uno de ellos se puede representar con
tres dı́gitos binarios:
• 000
• 001
• 010
• 011
• 100
• 101
• 110
• 111
Para convertir entre bases 2 y 8 basta con reemplazar cada grupo de tres dı́gitos binarios
(completando con ceros a la izquierda si hace falta) por el dı́gito octal equivalente. Lo mismo si
la conversión es en el otro sentido. La figura 2.4 muestra un ejemplo.
Para convertir de base 2 a base 16 simplemente hay que agrupar los dı́gitos binarios de a
cuatro, y reemplazar cada grupo de cuatro dı́gitos por su equivalente en base 16 según la tabla
anterior. Si hace falta completar un grupo de cuatro dı́gitos binarios, se completa con ceros a
la izquierda. Para convertirde base 16 a base 2, reemplazamos cada dı́gito hexadecimal por los
cuatro dı́gitos binarios que lo representan.
Capı́tulo 3
Unidades de Información
En este capı́tulo veremos qué es la información y cómo podemos cuantificarla, es decir, como
podemos medir la cantidad de información que, por ejemplo, puede guardar un dispositivo.
Veremos además las relaciones entre las diferentes unidades de información.
A lo largo de la historia se han inventado y fabricado máquinas, que son dispositivos que
transforman la energı́a, es decir, convierten una forma de energı́a en otra. Las computadoras,
en cambio, convierten una forma de información en otra. Los programas de computadora
reciben alguna forma de información (la entrada del programa), la procesan de alguna manera,
y emiten alguna información de salida. La entrada es un conjunto de datos de partida para
que trabaje el programa, y la salida generada por el programa es alguna forma de respuesta o
solución a un problema. Sabemos, además, que el material con el cual trabajan las computadoras
son números, textos, mensajes, imágenes, sonido, etc. Todas estas son formas en las que se
codifica y se almacena la información.
Un epistemólogo dice que la información es una diferencia relevante. Si vemos que el semáforo
cambia de rojo a verde, recibimos información (podemos avanzar). Al cambiar el estado del
semáforo aparece una diferencia que puedo observar. Es relevante porque modifica de alguna
forma el estado de mi conocimiento o me permite tomar una decisión respecto de algo.
3.2. El Bit
La Teorı́a de la Información, una teorı́a matemática desarrollada alrededor de 1950, dice que
el bit es la mı́nima unidad de información. Un bit es la información que recibimos cuando se es-
pecifica una de dos alternativas igualmente probables. Si tenemos una pregunta binaria, es decir,
aquella que puede ser respondida con un sı́ o con un no, entonces, al recibir una respuesta,
estamos recibiendo un bit de información. Las preguntas binarias son las más simples posibles
(porque no podemos decidir entre menos respuestas), de ahı́ que la información necesaria para
responderlas sea la mı́nima unidad de información.
De manera que un bit es una unidad de información que puede tomar sólo dos valores.
Podemos pensar estos valores como verdadero o falso, como sı́ o no, o como 0 y 1. La
memoria de las computadoras está diseñada de forma que le premite almacenar dos estados
en cada celda. Cuando las computadoras trabajan con piezas de información complejas, como
los textos o imágenes, estas piezas son representadas como conjuntos ordenados de bits, de un
cierto tamaño. Ası́, por ejemplo, la secuencia de ocho bits 01000001 puede representar la letra
15
16 CAPÍTULO 3. UNIDADES DE INFORMACIÓN
A mayúscula. Un documento estará constituido por palabras; éstas están formadas por sı́mbolos
como las letras, y éstas serán representadas por secuencias de bits. Todo lo que puede guardar,
procesar, o emitir una computadora digital, está representado por una secuencia de bits. Los bits
son, en cierta forma, como los átomos de la información. Por eso el bit es la unidad fundamental
que usamos para medirla, y definiremos también algunas unidades mayores.
En una famosa pelı́cula de aventuras hay una ciudad en problemas. Uno de las héroes enciende
una pila de leña porque se prepara un terrible ataque sobre la ciudad. La pila de leña es el
dispositivo preestablecido que tiene la ciudad para pedir ayuda en caso de emergencia.
En la cima de la montaña que está cruzando el valle existe un puesto similar, con su propio
montón de leña, y un vigı́a. Quien vigı́a ve el fuego encendido en la ciudad que pide ayuda, y a su
vez enciende su señal. Lo mismo se repite de cumbre en cumbre, atravesando grandes distancias
en muy poco tiempo, hasta llegar rápidamente a quienes están en condiciones de prestar la
ayuda. La información que está transportando la señal que viaja es la respuesta a una pregunta
muy sencilla: ¿la ciudad necesita nuestra ayuda?. Esta pregunta es binaria: se responde
con un sı́ o con un no. Por lo tanto, lo que ha viajado es un bit de información. En una
tragedia griega se dice que este ingenioso dispositivo se utilizó en la realidad, para comunicar en
tan sólo una noche la noticia de la caı́da de Troya.
Notemos que en los manuales de lógica o de informática, encontraremos siempre asociados
los bits con los valores 0 y 1. Aunque lo que viajó desde la ciudad sitiada hasta su destino no
es un 0 ni un 1, es un bit de información. Sin embargo, la identificación de los bits con los
dı́gitos binarios es útil para todo lo que tiene que ver con las computadoras.
3.3. El Byte
Como el bit es una medida tan pequeña de información, resulta necesario definir unidades más
grandes. En particular, y debido a la forma como se organiza la memoria de las computadoras,
es útil tener como unidad al byte (abreviado B mayúscula), que es una secuencia de 8 bits (ver
figura 3.3). Podemos imaginarnos la memoria de las computadoras como una estanterı́a muy
alta, compuesta por estantes que contienen ocho casilleros. Cada uno de estos estantes es una
posición o celda de memoria, y contiene exactamente ocho bits (un byte) de información.
Como los valores de los bits que forman un byte son in-
dependientes entre sı́, existen 28 diferentes valores para esos
ocho bits. Si los asociamos con números en el sistema bi-
nario, esos valores serán 00000000, 00000001, 00000010,
. . . , etc., hasta el 11111111. En decimal, esos valores co-
rresponden a los números 0, 1, 2, . . . , 255.
Un byte son 8 bits Cada byte de la memoria de una computadora, entonces,
puede alojar un número entre 0 y 255. Esos números repre-
sentarán diferentes piezas de información: si los vemos como
bytes independientes, pueden representar caracteres como letras y otros sı́mbolos, pero tam-
bién pueden estar formando parte de otras estructuras de información más complejas, y tener
otros significados.
3.4. SISTEMAS DE MEDICIÓN 17
Como puede verse, cada unidad se forma multiplicando la anterior por 1000.
En el llamado Sistema de Prefijos Binarios, el byte se multiplica por potencias de 210 , que
es 1024. Ası́, tenemos:
Como puede verse, cada unidad se forma multiplicando la anterior por 1024.
¿Por qué existen dos sistemas en lugar de uno? En realidad la adopción del Sistema de
Prefijos Binarios se debe a las caracterı́sticas de la memoria de las computadoras:
Veremos en este capı́tulo cómo pueden representarse datos numéricos (enteros y fraccionarios)
mediante patrones de bits. Idealmente, un sistema de numeración puede usar infinitos dı́gitos
para representar números arbitrariamente grandes. Si bien esto es matemáticamente correcto, las
computadoras tienen limitaciones fı́sicas, y con ellas no es posible representar números de infinita
cantidad de dı́gitos. Es por esto en siempre que trabajemos con un sistema de representación de
datos debemos conocer la cantidad de bits de que disponemos.
Es importante recordar que solo se puede operar entre datos representados con el mismo
sistema de representación, y que el resultado de esta operación estará representado en ese sistema.
Por ejemplo, si tenemos dos valores A y B, y queremos sumarlos, ambos valores deben estar
representados en el mismo sistema.
Cuántos
Veamos cómo calcular cuántos valores diferentes podemos representar con una cantidad fija
de bits. Veamos un ejemplo con pocos bits. Si tenemos 3 bits, todos los números representables
son los siguientes:
19
20 CAPÍTULO 4. REPRESENTACIÓN DE DATOS NUMÉRICOS
Decimal Binario
0 000
1 001
2 010
3 011
4 100
5 101
6 110
7 111
Si observamos esta tabla, vemos que, usando 3 bits, podemos representar ocho números
diferentes (del 0 al 7), y ocho es justamente 23 , donde 2 es la base del sistema (estamos trabajando
con sistema binario) y 3 es la cantidad de bits. Recordemos que como estamos estudianto sistemas
de representación de datos en la computadora, debemos atenernos a una cantidad fija de bits.
A esa cantidad fija de bits la nombraremos k.
¿Cuántos valores diferentes podemos representar con k bits? Con k bits, podemos representar
2k valores diferentes.
Cuáles
¿Cómo interpretar esos 2k valores diferentes? Dependerá del sistema de representación que
estemos utilizando. En nuestro ejemplo de 3 bits, el sistema de representación que usemos definirá
cómo interpretar esos 8 valores diferentes. Por ejemplo, en un sistema de representación .A”, el
”111”puede significar 7(10) , mientras que en otro sistema de representación ”B”, el ”111”puede
representar −1(10) , y ası́. Entonces, cuando nos preguntemos ¿qué valor representa el ”111¿ La
respuesta es: Depende! ¿De qué depende? Del sistema de representación con el que estemos
trabajando.
¿Cuáles valores podemos representar con k bits? Depende del sistema de representación que
usemos.
Preguntas de repaso
¿Cuáles son los lı́mites del rango de representación de un sistema de representación numéri-
ca?
¿Cuántos valores diferentes podemos representar con k bits?
¿Cuál será el rango de representación de este sistema? El cero puede representarse, ası́ que el
lı́mite inferior del rango de representación será 0. Pero ¿cuál será el lı́mite superior? Es decir, si
la cantidad de dı́gitos binarios en este sistema es k, ¿cuál es el número más grande que podremos
representar? La respuesta es: 2k − 1
Por lo tanto, el rango de representación de un sistema sin signo con k dı́gitos es
[0, 2k − 1]. Todos los números representables en esta clase de sistemas son positivos o cero.
4.3. SISTEMA DE REPRESENTACIÓN CON SIGNO 21
Ejemplos
7(10 = 00000111(2
−7(10 = 10000111(2
Existen dos representaciones del 0 (una ”positiva otra ”negativa), lo cual desperdicia una
2
secuencia de bits que podrı́a usarse para representar otro número y ampliar el RR.
La aritmética en SM no es fácil, ya que cada operación debe comenzar por averiguar si los
operandos son positivos o negativos, operar con los valores absolutos y ajustar el resultado
de acuerdo al signo reconocido anteriormente.
El problema aritmético se agrava con la existencia de las dos representaciones del cero:
cada vez que un programa quisiera comparar un valor resultado de un cómputo con 0,
deberı́a hacer dos comparaciones.
Por estos motivos, el sistema de SM dejó de usarse y se diseñó un sistema que eliminó estos
problemas, el sistema de complemento a 2.
Se invierte cada uno de los bits (es decir, cada cero se reemplaza por uno, y cada uno se
reemplaza por cero.
Se suma 1 al resultado de la inversión de bits.
Propiedad fundamental
El resultado de aplicar la operación C2(a), es el opuesto del número original a, y por lo tanto
tiene la propiedad de que
C2(a) + a = 0
Comprobación
4.5. SISTEMA DE REPRESENTACIÓN Y OPERACIÓN COMPLEMENTO A 2 23
Ejemplos
Ejemplos
4.5.6. Aritmética en C2
Una gran ventaja que aporta el sistema en Complemento a 2 es que los diseñadores de
hardware no necesitan implementar algoritmos de resta. Cuando se necesita efectuar una resta,
se complementa el sustraendo y luego se lo suma al minuendo. Las computadoras no restan:
siempre suman.
Por ejemplo, la operación 9 − 8 se realiza como 9 + (−8), donde (-8) es el complemento a 2
de 8.
Preguntas para pensar
Para el caso particular de la suma aritmética de operandos en C2, una forma sencilla de
detectar overflow es comparando los dos últimos acarreos de la operación. ¿Qué es el acarreo
(o carry en inglés)? En aritmética, el acarreo es el nombre utilizado para describir un recurso
mnemotécnico en una operación aritmética, principalmente en la operación suma1 . En la Figura
4.2 vemos un ejemplo de una suma, donde el dı́gito 1 es el acarreo.
Ahora bien, volviendo al méto-
do para la detección del overflow en
una operación de suma en C2, lo que
debemos hacer es comparar los dos
últimos acarreos, es decir el último
carry-in con el último carry-out. El
acarreo que ingresa a una columna
se denomina carry-in, mientras que
Figura 4.2: Acarreos o carris de una suma aritmética. al acarreo que sale de una suma (pa-
ra ir a la columna siguiente) se de-
nomina carry-out. El procedimiento
es el siguiente:
Si, luego de efectuar una suma en C2, los valores de los bits del último carry-in y el último
carry-out son iguales, entonces la computadora detecta que el resultado no ha desbordado
y que la suma es válida. La operación de suma se ha efectuado exitosamente.
Si, luego de efectuar una suma en C2, los valores de los bits del último carry-in y del
último carry-out son diferentes, entonces la computadora detecta que el resultado ha
desbordado y que la suma no es válida. La operación de suma no se ha llevado a cabo
exitosamente, y el resultado debe ser descartado.
Veamos otro ejemplo, la operación 123 + 9 en C2 a 8 bits. El resultado (que es 132) cae fuera
del rango de representación. Si hacemos la suma de esos valores en binario y revisamos los dos
últimos bits de acarreo deberı́an ser diferentes. Puede verificarlo? Primero hay que convertir esos
valores en decimal a binario usando el sistema de representación de datos C2, con 8 bits. Luego
hacer la suma, anotando todos los acarreos. Finalmente comparar los dos últimos acarreos. Sin
son diferentes, es poque hubo overflow.
Preguntas
¿Qué condición sobre los bits de carry permite asegurar que no habrá overflow?
¿Para qué sistemas de representación numérica usamos la condición de detección de over-
flow?
¿Puede existir overflow al sumar dos números de diferente signo?
¿Qué condición sobre los bits de signo de los operandos permite asegurar que no habrá over-
flow?
¿Puede haber casos de overflow al sumar dos números negativos?
¿Puede haber casos de overflow al restar dos números?
En una suma en C2, si uno de los operandos estuviera expresado con menos bits que el otro,
será necesario extenderlo hasta el ancho del operando de mayor cantidad de bits, y operar
con ambos operandos con el mismo ancho. Si el operando a extender es positivo, la extensión
se realiza simplemente completando con ceros a la izquierda hasta obtener la cantidad de
dı́gitos necesaria. Si el operando a extender es negativo, la extensión de signo se hace agregando
unos.
Ejemplos
A + B = 00101011(2 + 00101(2
• A está en C28 y B en C25 → llevar ambos a C28
• Se completa B (positivo) como 00000101(2
A + B = 1010(2 + 0110100(2
• A está en C24 y B en C27 → llevar ambos a C27
• Se completa A (negativo) como 1111010(2
4.6. NOTACIÓN EN EXCESO 27
000 =a
001 = a+1
010 = a+2
...
111 =b
Notemos que tanto a como b pueden ser positivos o negativos. Ası́ podemos representar
intervalos de enteros arbitrarios con secuencias de k bits, lo que nos vuelve a dar un sistema
de representación con signo. Con este método no es necesario que el bit de orden más alto
represente el signo. Tampoco que el intervalo contenga la misma cantidad de números negativos
que positivos o cero, aunque para la mayorı́a de las aplicaciones es lo más razonable.
El sistema en exceso se utiliza como componente de otro sistema de representación más
complejo, la representación en punto flotante (que veremos mas adelante).
Una vez establecido un sistema en exceso que representa el intervalo [a, b] en k bits:
Ejemplos
Representemos en el sistema de representación en exceso el intervalo [10, 25] (que contiene
25 − 10 + 1 = 16 enteros). Como necesitamos numerar 16 ı́tems, usaremos 4 bits que producirán
las secuencias 0000, 0001, . . . , 1111.
Para calcular la secuencia que corresponde al número 20, hacemos 20 − 10 = 10, lo con-
vertimos a SS(k=4) y el resultado será el binario 1010.
Para calcular el valor decimal que está representando la secuencia 1011, convertimos 1011
a decimal, que es 11, y le sumamos 10 (que es el lı́mite inferior del intervalo [a,b]); el
resultado es 21.
28 CAPÍTULO 4. REPRESENTACIÓN DE DATOS NUMÉRICOS
Para convertir a binario un número con decimales que está en base 10, se convierte la parte
entera y la parte decimal de manera separada. Para calcular la parte fraccionaria binaria de n
seguimos un procedimiento iterativo (es decir, que consta de pasos que se repiten). El método
consiste en:
2. La parte entera se convierte a base 2 como entero sin signo dando 11(2) .
6. Las partes enteras parciales (que se fueron guardando) fueron 1, 0 y 1, dando la parte
fraccionaria final ,101(2 . A esta parte fraccionaria se le suma la parte entera: 11(2 +0,101(2 =
11,101(2 .
Los sistemas de punto fijo establecen una cantidad fija de bits o ancho total (que llamaremos
n) y una cantidad fija de bits para la parte fraccionaria (que llamaremos k). Por ejemplo, la
notación P F (8, 3) denota un sistema de punto fijo con 8 bits en total, de los cuales 3 son para la
parte fraccionaria. Al ser fijos los anchos de parte entera y fraccionaria, la computadora puede
tratar aritméticamente a todos los números como si fueran enteros, sin preocuparse
por partes enteras ni fraccionarias. Solamente habrá que utilizar la convención al momento de
imprimir o comunicar un resultado. La impresora, o la pantalla, deberán mostrar un resultado
con coma fraccionaria en el lugar correcto.
Ejemplo
completaremos la parte fraccionaria con ceros por la derecha, hasta obtener k dı́gitos. Una vez
expresado ası́, lo tratamos como si en realidad fuera a × 2k , y por lo tanto, un entero.
Truncamiento
Cuando vimos enteros, vimos que con cierta cantidad de bits podı́amos representar valo-
res dentro de un Rango de Representación. Valores fuera de ese rango no eran representables
(porque los bits no alcanzaban). En los números fraccionarios veremos que la cantidad de bits
designados para la parte fraccionaria puede no ser suficiente para representar la totalidad de los
decimales, pero podemos representar una aproximación al número, truncando algunos decima-
les. El número almacenado en el sistema PF(n,k) será una aproximación al número original, y no
estará representándolo con todos sus dı́gitos fraccionarios. La consecuencia de este truncamiento
es la aparición de un error de truncamiento o pérdida de precisión. Si quisiéramos conocer de
cuánto es ese error, deberı́amos calcular la diferencia entre el número que queremos representar,
y el número finalmente representado por la computadora. Veamos un ejemplo.
Para convertir un binario en notación de punto fijo en n lugares con k fraccionarios (PF(n,k))
a decimal:
Preguntas de repaso
• 0001,1000?
• 0000,1100?
¿Cómo se representan en P F (8, 4). . .
• 0,5?
• −7,5?
¿Cuál es el RR de P F (8, 3)? ¿Y de P F (8, k)?
La principal ventaja de la representación en punto fijo provienen, sobre todo, de que permite
reutilizar completamente la lógica ya implementada para tratar enteros en complemento a 2,
sin introducir nuevos problemas ni necesidad de nuevos recursos. Como la lógica para C2 es
sencilla y rápida, la representación de punto fijo es adecuada para sistemas que deben ofrecer
una determinada performance:
Los sistemas que deben ofrecer un tiempo de respuesta corto, especialmente aquellos in-
teractivos, como los juegos.
Los sistemas de tiempo real, donde la respuesta a un cómputo debe estar disponible en un
tiempo menor a un plazo lı́mite, generalmente muy corto.
Los sistemas empotrados o embebidos, que suelen enfrentar restricciones de espacio de
memoria y de potencia de procesamiento.
La principal desventaja puede ser que no es una representación adecuada para cierta clase
de problemas donde los datos que se manejan son de magnitudes y precisiones muy diferentes
entre sı́. Por ejemplo, si un programa de cómputo cientı́fico necesita calcular el tiempo en
que la luz recorre una millonésima de milı́metro, la fórmula a aplicar relacionará la
velocidad de la luz en metros por segundo (unos 300,000,000 m/s) con el tamaño en metros de
un nanómetro (0,000000001 m). Estos dos datos son extremadamente diferentes en magnitud y
cantidad de dı́gitos fraccionarios. La velocidad de la luz es un número astronómicamente grande
en comparación a la cantidad de metros en un nanómetro; y la precisión con que necesitamos
representar al nanómetro, no es necesaria para representar la velocidad de la luz.
Cuando las magnitudes de los datos son muy variadas, habrá datos de valor absoluto muy
grande, lo que hará que sea necesario elegir una representación de una gran cantidad de
bits de ancho. Pero esta cantidad de bits quedará desperdiciada al representar los datos
de magnitud pequeña.
Otro tanto ocurre con los bits destinados a la parte fraccionaria. Si los requerimientos de
precisión de los diferentes datos son muy altos, será necesario reservar una gran cantidad
de bits para la parte fraccionaria. Esto permitirá almacenar los datos con mayor cantidad
de dı́gitos fraccionarios, pero esos bits quedarán desperdiciados al almacenar otros datos.
En Matemática, la respuesta al problema del cálculo con datos con valores muy diferentes
existe desde hace mucho tiempo, y es la llamada Notación Cientı́fica. En Notación Cientı́fica,
los números se expresan en una forma estandarizada que consiste de un coeficiente, signi-
ficando o mantisa multiplicado por una potencia de 10. Es decir, la forma general de la
notación es m × 10e , donde m, el coeficiente, es un número positivo o negativo, y e, el
exponente, es un entero positivo o negativo.
4.8. REPRESENTACIÓN DE NÚMEROS FRACCIONARIOS 33
La notación cientı́fica puede representar entonces números muy pequeños y muy grandes,
todos en el mismo formato, lo que permite operar entre ellos con facilidad. Al operar con números
en esta notación podemos aprovechar las reglas del álgebra para calcular m y e separadamente,
y evitar cuentas con muchos dı́gitos.
Ejemplo
La velocidad de la luz expresada en metros por segundo, 300,000,000 m/s aproximadamente,
expresada en Notación Cientı́fica es: 3 × 108 m/s. La longitud en metros de un nanómetro, se
representará en notación cientı́fica como 1 × 10−9 .
El tiempo en que la luz recorre una millonésima de milı́metro se computará con la fórmula
t = e/v, con los datos expresados en notación cientı́fica, como:
e = 1 × 10−9 m
v = 3 × 108 m/s
t = e/v = (1 × 10−9 m)/(3 × 108 m/s) =
t = 1/3 × 10−9−8 s =
t = 0,333 × 10−17 s
Normalización
El resultado que hemos obtenido en el ejemplo anterior debe quedar normalizado llevando
el coeficiente m a un valor mayor o igual que 1 y menor que 10. Si modificamos el coeficiente
al normalizar, para no cambiar el resultado debemos ajustar el exponente.
Ejemplo
El resultado que obtuvimos anteriormente al computar t = 1/3×10−9−8 s fue 0,333×10−17 s.
Este coeficiente 0,333 no cumple la regla de normalización porque no es mayor o igual que 1.
Normalización en base 2
Es perfectamente posible definir una notación cientı́fica en otras bases. En base 2, podemos
escribir números con parte fraccionaria en notación cientı́fica normalizada desplazando la coma
o punto fraccionario hasta dejar una parte entera igual a 1 (único valor que cumple la condición
de normalización) y ajustando el exponente de base 2, de manera de no modificar el resultado.
Ejemplos
100,111(2 = 1,00111(2 × 22
0,0001101(2 = 1,101(2 × 2−4
flotante. Estos métodos resuelven los problemas de los sistemas de punto fijo, abandonando
la idea de una cantidad fija de bits para parte entera y parte fraccionaria. Inspirándose en la
notación cientı́fica, los formatos de punto flotante permiten escribir números de un gran rango
de magnitudes y precisiones en un campo de tamaño fijo.
Actualmente se utilizan los estándares de cómputo en punto flotante definidos por la orga-
nización de estándares IEEE (Instituto de Ingenierı́a Eléctrica y Electrónica). Estos estándares
son dos, llamados IEEE 754 en precisión simple y en precisión doble.
Ejemplo
Recorramos los pasos para la conversión manual a punto flotante precisión simple, partiendo
del decimal n = −5,5. Recordemos que necesitamos averiguar s, e y m.
4.8. REPRESENTACIÓN DE NÚMEROS FRACCIONARIOS 35
n es negativo, luego s = 1.
|n| = 5,5. Convirtiendo el valor absoluto a binario obtenemos 101,1(2 .
Normalizando, queda 101,1(2 = 1,011(2 × 22 .
Del paso anterior, el exponente 2 se representa en exceso a 127 como e = 2 + 127 = 129.
En base 2, 129 = 10000001(2 .
Del mismo paso anterior extraemos la mantisa quitando la parte entera: 1,011 − 1 = 0,011.
Los bits de m son 011000000... con ceros hasta la posición 23.
Finalmente, s, e, m = 1, 10000001, 011000000000....
Para facilitar la escritura y comprobación de los resultados, es conveniente leer los 32 bits de
la representación en punto flotante precisión simple como si se tratara de 8 dı́gitos hexadecimales.
Se aplica la regla, que ya conocemos, de sustituir directamente cada grupo de 4 bits por un dı́gito
hexadecimal.
Ası́, en el ejemplo anterior, la conversión del decimal −5,5 resultó en la secuencia de bits
11000000101100000000000000000000.
Es fácil equivocarse al transcribir este resultado. Pero sustituyendo los bits de a grupos de
4 por dı́gitos hexadecimales, obtenemos la secuencia equivalente C0B00000, que es más simple
de leer y de escribir.
Teniendo un número expresado en punto flotante precisión simple, queremos saber a qué
número decimal equivale. Separamos la representación en sus componentes s, e y m, que tienen
1, 8 y 23 bits respectivamente, y deshacemos los pasos hechos anteriormente para convertir
un decimal a punto flotante.
Signo
• El valor de s nos dice si el decimal es positivo o negativo.
• La fórmula (−1)s da -1 si s = 1, y 1 si s = 0.
Exponente
• El exponente está almacenado en la representación IEEE 754 como ocho bits en exceso
a 127. Corresponde restar 127 para volver a obtener el exponente de 2 que afectaba
al número originalmente en notación cientı́fica normalizada.
• La fórmula 2(e−127) dice cuál es la potencia de 2 que debemos usar para ajustar la
mantisa.
Mantisa
• La mantisa está almacenada sin su parte entera, que en la notación cientı́fica norma-
lizada en base 2 siempre es 1. Para recuperar el coeficiente o mantisa original hay
que restituir esa parte entera igual a 1.
• La fórmula 1 + m nos da la mantisa binaria original.
Reuniendo las fórmulas aplicadas a los tres elementos de la representación, hacemos el cálculo
multiplicando los tres factores:
36 CAPÍTULO 4. REPRESENTACIÓN DE DATOS NUMÉRICOS
n = (−1)s × 2(e−127) × (1 + m)
Signo
• (−1)s = (−1)1 = −1
Exponente
• e = 129 → 2(e−127) = 22
Mantisa
• m = 0110000... → (1 + m) = 1,011000....
Aunque los 23 bits de mantisa del formato de punto flotante en precisión simple son suficientes
para la mayorı́a de las aplicaciones, existen números que no pueden ser representados, ni aun en
doble precisión. Un número que cae fuera del rango de representación porque es muy grande, es
fácil de ver. Ahora bien, ¿qué sucede con los números muy pequeños?
Existe, por otro lado, un problema al tratar con números como 0.1 o 0.2. ¿Cuál es el problema
en este caso? Si hacemos manualmente el cálculo de la parte fraccionaria binaria de 0.1 (o de
0.2) encontraremos que esta parte fraccionaria es periódica. Esto ocurre porque 0,1 = 1/10, y
el denominador 10 contiene factores que no dividen a la base (es decir, el 5, que no divide a 2).
Lo mismo ocurre en base 10 cuando computamos 1/3, que tiene infinitos decimales periódicos
porque el denominador 3 no divide a 10, la base.
Cuando un lenguaje de programación reconoce una cadena de caracteres como 0.1, introdu-
cida por la persona que programa o usa el programa, advierte que se está haciendo referencia
a un número con decimales, e intenta representarlo en la memoria como un número en punto
flotante. La parte fraccionaria debe ser forzosamente truncada, ya sea a los 23 bits, porque
se utiliza precisión simple, o a los 52 bits, cuando se utiliza precisión doble. En ambos casos,
el número representado es una aproximación al 0.1 original, y esta aproximación será mejor
cuantos más bits se utilicen; pero en cualquier caso, esta parte fraccionaria almacenada en la
representación en punto flotante es finita, de manera que nunca refleja el verdadero valor que
le atribuimos al número original. A partir del momento en que ese número queda representa-
do en forma aproximada, todos los cómputos realizados con esa representación adolecen de un
error de truncamiento, que va agravándose a medida que se opera con los resultados que van
arrastrando el error.
En precisión simple, se considera que tan sólo los primeros siete decimales de un número
en base 10 son representados en forma correcta. En precisión doble, sólo los primeros quince
decimales son correctos.
4.8. REPRESENTACIÓN DE NÚMEROS FRACCIONARIOS 37
En el capı́tulo anterior vimos cómo podemos representar datos numéricos (enteros, fracciona-
rios). En este capı́tulo veremos cómo podemos representar otras clases de datos (no numéricos):
textos e imágenes.
En general, prácticamente todos los sı́mbolos que figuran en nuestro teclado tienen un código
39
40 CAPÍTULO 5. REPRESENTACIÓN DE TEXTO E IMÁGENES
ASCII asignado. Como sólo se usan siete bits, el bit de mayor orden (el de más a la izquierda)
de cada byte siempre es cero, y por lo tanto los códigos ASCII toman valores de 0 a 127.
Como solo dispone de 128 posibles caraceteres, esta forma de codificar caracteres no contem-
pla las necesidades de diversos idiomas. Por ejemplo, nuestra letra Ñ no figura en la tabla ASCII.
Tampoco las vocales acentuadas, ni con diéresis, como tampoco decenas de otros caracteres de
varios idiomas europeos. Peor aún, con solamente 128 posibles patrones de bits, es imposible
representar algunos idiomas orientales como el chino, que utilizan miles de ideogramas. Por este
motivo se estableció más tarde una familia de nuevos estándares, llamada Unicode. Uno de los
estándares o esquemas de codificación definidos por Unicode, el más utilizado actualmente, se
llama UTF-8. Este estándar mantiene la codificación que ya empleaba el código ASCII para su
conjunto de caracteres, pero agrega códigos de dos, tres y cuatro bytes para otros sı́mbolos. El
resultado es que hoy, con UTF-8, se pueden representar todos los caracteres de cualquier idioma
conocido.
Otro estándar utilizado, ISO/IEC 8859-1, codifica los caracteres de la mayorı́a de los
idiomas de Europa occidental.
5.2.1. Digitalización
Introducir en la computadora una imagen analógica (tal como un dibujo o una pintura hecha
a mano), o un fragmento de sonido tomado del ambiente, requiere un proceso de digitalización.
Digitalizar es convertir en digital la información que es analógica, esto se hace convirtiendo un
rango continuo de valores (lo que está en la naturaleza) a un conjunto discreto de valores
numéricos.
Si partimos de una imagen analógica, el proceso de digitalización involucra la división de la
imagen en una fina cuadrı́cula, donde cada elemento de la cuadrı́cula abarca un pequeño sector
cuadrangular de la imagen. A cada elemento de la cuadrı́cula se le asigna un valor que codifica el
color de la imagen en ese lugar. Estos elementos o puntos se llaman pixels (del inglés, picture
element). La imagen queda constituida por una sucesión de valores de color para cada pixel
de los que forman la imagen. En general, mientras más elementos de cuadrı́cula (más pixels)
podamos representar, mejor será la aproximación a nuestra imagen original. Mientras más fina
la cuadrı́cula (es decir, mientras mayor sea la resolución de la imagen digitalizada), y mientras
más valores discretos usemos para representar los colores, más se parecerá nuestra versión digital
al original analógico.
Notemos que la digitalización de una imagen implica la discretización de dos variables
analógicas:
Por un lado, los infinitos puntos de la imagen analógica bidimensional, deben reducirse a
unos pocos rectángulos discretos.
Por otro lado, los infinitos valores de color deben reducirse a unos pocos valores discretos,
en el rango de nuestro esquema de codificación.
Este proceso de digitalización es el que hacen automáticamente una cámara de fotos digital
o un celular, almacenando luego los bytes que representan la imagen tomada.
Color
Cuando se crea una mezcla de rayos de luz de colores con diferentes intensidades, usando
un proyector o una pantalla como los displays LED, las ondas luminosas individuales del rojo,
5.2. REPRESENTACIÓN DE IMAGEN 41
verde y azul se suman formando otros colores. Este esquema de representación del color se llama
RGB por las iniciales de los colores rojo, verde y azul en inglés.
Una forma de representar el color en las imágenes digitales es definir, para cada pixel, tres
coordenadas (valores) que describen las intensidades de luz roja, verde y azul que conforman
el color de ese pixel.
Cuando las coordenadas se representan usando un byte, cada coordenada puede tomar un
valor entre 0 y 255. Ası́, la terna (0, 0, 0) representa el negro (ausencia de los tres colores), la
terna (255, 255, 255) el blanco (valores máximos de los tres colores, sumados), etc.
Con este esquema de representación de color, cada pixel o elemento de la imagen quedarı́a
representado por tres bytes, o 24 bits. Sin embargo, las cámaras fotográficas digitales modernas
utilizan un esquema de codificación con mucha mayor profundidad de color. La profundidad
de color se define como la cantidad de bits utilizados para la codificación de los colores de la
imagen.
Lógicamente, para las imágenes con muchos colores (como las escenas de la naturaleza donde
hay gradaciones de colores) es conveniente contar con muchos bits de profundidad de color. Sin
embargo, cuando una imagen se compone de pocos colores, la imagen digital es innecesariamente
grande, costosa de almacenar y de transmitir. En estos casos es útil definir un formato de
imagen que represente esos pocos colores utilizando menos bits. Una forma de hacerlo es definir
una paleta de colores, que es una lista de los diferentes colores utilizados en la imagen,
codificados con la menor cantidad de bits posible. Si conocemos la cantidad de colores en la
imagen, podemos determinar la cantidad mı́nima de bits que permite codificarlos a todos. Ası́,
cada pixel de la imagen, en lugar de quedar representado por una terna de valores (como en la
representación RGB), puede representarse por un número de color en la paleta.
Queda por especificar cuál color es el que está codificado por cada número de color
de la paleta. Si una imagen tiene dos bits de profundidad de color, los colores serán cuatro, y
sus códigos serán 00, 01, 10, 11. Pero, ¿cuáles exactamente son estos colores? Tal vez, blanco,
negro, rojo y azul. Pero tal vez sean cuatro niveles de gris. O cuatro diferentes tonos de verde.
Además de la sucesión de bits que codifican los colores de los pixels, y de conocer la profun-
didad de color, para poder representar la imagen, necesitamos conocer el ancho y el alto de la
misma.
Por ejemplo, un archivo que define una imagen de cinco por cinco pixels, a cuatro
colores, comienza con los bytes 00000101, 00000101, 00000010, y sigue con los datos de la
imagen. Como leer y escribir binario puede ser confuso, escribiremos esta representación en
hexadecimal cuando ası́ lo precisemos.
Para interpretar qué imagen describe un archivo dado, consideramos primero su cabecera y
buscamos cuál es el ancho y el alto (indicados por los primeros dos bytes), y cuántos bits por
pixel están codificados en el resto del archivo (indicados por el tercer byte). De esta manera
podemos dibujar la imagen.
Ejemplo
Muchas veces es interesante reducir el tamaño de un archivo, para que ocupe menos espacio
de almacenamiento o para que su transferencia a través de una red sea más rápida. Al ser todo
archivo una secuencia de bytes, y por lo tanto de números, disponemos de métodos y herramien-
tas matemáticas que permiten, en ciertas condiciones, reducir ese tamaño. La manipulación de
los bytes de un archivo con este fin se conoce como compresión. El algoritmo de compresión
puede ser de sin pérdida, o con pérdida.
Decimos que la compresión ha sido sin pérdida cuando puede extraerse del archivo compri-
mido exactamente la misma información que antes de la compresión, utilizando otro algoritmo
que ejecuta el trabajo inverso al de compresión. En otras palabras, la compresión sin pérdida
es reversible: aplicando el algoritmo inverso, o de descompresión, siempre puede volverse a la
información de partida. Esto es un requisito indispensable cuando necesitamos recuperar exac-
tamente la secuencia de bytes original, como en el caso de un archivo de texto, una base de
datos, una planilla de cálculo.
Como usuarios de computadoras, es muy probable que hayamos utilizado más de una vez la
compresión sin pérdida, al tener que comprimir un documento de texto, utilizando un programa
utilitario como ZIP, RAR u otros. Si la compresión no fuera reversible, no podrı́amos recuperar
el archivo de texto tal cual fue escrito.
5.2. REPRESENTACIÓN DE IMAGEN 43
A veces usamos compresión al consultar páginas de Internet. Muchos sitios utilizan compre-
sión para acelerar la descarga de sus contenidos. Los navegadores cuentan con el conocimiento
para identificar cuándo una página está comprimida, y saben descomprimirla en forma transpa-
rente, es decir, sin que la usuaria lo note.
Reducción de color
Si la imagen tiene ancho × alto pixels, y la información de color es de n bits por pixel, el
archivo sin su cabecera mide ancho×alto×n bits. Una forma sencilla de compresión con pérdida,
que no modifica la resolución, es la reducción de la profundidad de color de una imagen. Si la
imagen puede seguir siendo útil con menos colores, comprimiendo la paleta de colores puede
obtenerse un archivo de menor tamaño.
Comprimir la paleta de colores consiste en reescribir la imagen con una cantidad menor de
bits por pixel. Cada vez que la cantidad de bits por pixel decrece en uno, la profundidad de color,
es decir, la cantidad de colores diferentes, se divide por dos. De esta forma se puede reducir la
cantidad de bits utilizados para expresar cada pixel, claro está, al costo de perder información
de color de la imagen.
Ejemplo
Sea una imagen a cuatro colores; luego la cantidad de bits por pixel es 2. Al reducir la
profundidad de color, los colores 00 y 01 pasan a ser el único color 0; y los colores 10 y 11 pasan
a ser el único color 1. Todos los pixels quedan expresados por un único bit 0 o 1, reduciendo
efectivamente el tamaño de la imagen.
Dos pixels cuyos códigos de color diferı́an sólo en el bit de orden más alto ahora tendrán
el mismo código, y por lo tanto se pintarán del mismo color. El archivo ya no contiene la
información necesaria para saber cuál era el color original de cada pixel.
Ejemplo
Si el archivo está dado por la cadena hexadecimal 050502AEAFFAE8A600A8 (ancho: 5,
alto: 5, bits por pixel: 2, pixels: 10 10 11 10 10 10 11 11 11 11 10 10 11 10 10 00 10 10 01 10 00
00 10 10 10), los pasos del procedimiento anterior son:
La imagen comprimida queda como 05050123C82000 (ancho: 5, alto: 5, bits por pixel: 1,
pixels: 0 0 1 0 0 0 1 1 1 1 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0).
Pregunta
Aunque los programas que aplican algoritmos de compresión sin pérdida pueden ser muy
sofisticados, algunas ideas básicas son muy sencillas.
Supongamos tener una imagen en el formato que ya hemos descripto, y supongamos además
que los datos de la imagen, es decir, la sucesión de bits que codifican los pixels, presentan grandes
zonas de pixels con el mismo valor (muchos 1 seguidos, y muchos 0 seguidos). Si quisiéramos
transmitir esta información por teléfono a alguien más, para que la imagen pudiera ser dibujada
del otro lado, tarde o temprano la conversación incluirı́a frases como “. . . ahora cinco unos, ahora
doce ceros. . . ”. Esta forma de descripción es mucho más económica, y menos propensa a errores.
Resulta natural abreviar la descripción de la imagen usando este tipo de expresiones, donde
las cantidades funcionan como coeficientes. Un método inspirado directamente en esta idea
se llama Run Length Encoding (RLE) o Codificación por longitud de secuencia. Una
secuencia es una subsucesión de elementos del mismo valor. El método RLE identifica secuencias
5.2. REPRESENTACIÓN DE IMAGEN 45
Si los coeficientes son pequeños, y la redundancia del archivo es muy alta, no aprovecha-
remos la capacidad de compresión del método.
Si los coeficientes son muy grandes, y la imagen tiene poca redundancia, se desperdiciarán
bits en los coeficientes y no lograremos buena compresión.
Ejemplo
La compresión sin pérdida por el método de Huffmann utiliza códigos de longitud variable.
El método consiste esencialmente en examinar el archivo completo buscando subsecuencias de
bits repetidas. Se computa la frecuencia, o cantidad de veces que aparece, para cada una de
estas subsecuencias. Las subsecuencias se ordenan descendentemente por frecuencia, y cada una
se reemplaza por un código instantáneo de bits de longitud creciente.
Por ejemplo, el carácter más frecuente será reemplazado por el código 1; el siguiente en
frecuencia, por el código 01; el siguiente, por 001; etc. Ası́, los caracteres que aparecen más veces
serán codificados por patrones de bits más cortos. De esta forma el archivo comprimido ocupará
menos espacio que con un código de longitud uniforme.
Ejemplo
El texto de once caracteres “ABRACADABRA” contiene cinco “A”, dos “B”, dos “R”,
una “C” y una “D”. Si no utilizamos compresión, se necesitan 11 × 8 = 88 bits para
representarlo. Si utilizamos compresión por códigos de longitud variable, crearemos un
pequeño diccionario de la forma { A → 1, B → 01, R → 001, C → 0001, D → 00001 }.
Con este diccionario, el texto se podrá representar como “1 01 001 1 0001 1 00001 1 01
001 1”, en tan sólo 23 bits.
Interesante
Ley de Zipf
46 CAPÍTULO 5. REPRESENTACIÓN DE TEXTO E IMÁGENES
Fijada la cantidad de bits para coeficientes, la imagen se comprime indicando, para cada
secuencia de pixels iguales, qué factor de repetición corresponde y qué valor de color llevan los
pixels repetidos.
Ejemplo
La imagen con profundidad de color 2, cuyos datos de imagen son {10 10 11 11 11 11 11 11
11 10 10 10 10 10 10 00 . . . }, tiene una secuencia de dos pixels con valor 10, siete pixels
con valor 11, seis pixels con valor 10, etc.
Si utilizamos tres bits para el coeficiente, los coeficientes RLE 2, 7 y 6 se expresarán
como 010, 111 y 110. Los datos de la imagen se comprimirán como { 010 10 111 11 110 10. . .
}. Los primeros treinta bits de los datos de imagen han quedado comprimidos a quince bits.
Organización de Computadoras
En este capı́tulo veremos una descripción de los componentes de una computadora: memoria
principal, procesador, buses de interconexión, dispositivos de entrada y salida. Veremos sus
principales funciones y cómo se interrelacionan.
1. Memoria principal: Aquı́ se almacenan las instrucciones y los datos. Todo lo que puede
hacer la computadora, lo hace únicamente con contenidos que estén en la memoria. Para
poder procesar un dato, primero hay que hacerlo llegar a la memoria principal, no im-
porta de dónde venga. Un conjunto de datos puede estar en disco, en un pendrive, o ser
introducido por el teclado, pero sólo cuando llega a la memoria principal es que puede ser
procesado por la CPU.
La memoria es un componente fundamental de la computadora. Está implementada con
circuitos que pueden estar en uno de dos estados eléctricos, y por esto los llamamos bies-
tables. Cada circuito biestable puede almacenar la información correspondiente a un bit.
Los bits están agrupados de a ocho formando los bytes. Estos circuitos, con las tecnologı́as
de hoy, están super miniaturizados y contienen muchos millones de posiciones donde se
pueden almacenar temporariamente los datos y las instrucciones de programa.
Para poder utilizar la memoria es imprescindible conocer el número, o dirección, de la
posición de memoria donde está el dato o instrucción que se necesita acceder. Con esta
dirección podemos recuperar, es decir, leer, el valor que está alojado en ese byte de la
memoria, o escribir sobre ese byte un contenido de ocho bits.
2. Procesador: También llamado Unidad Central de Procesamiento (CPU por sus siglas en
inglés), es el lugar donde se ejecutan las instrucciones. Trabaja leyendo instrucciones y
datos de la memoria; y ejecuta esas instrucciones que operan sobre esos datos.
Un procesador consta de tres partes (ver figura 6.1):
47
48 CAPÍTULO 6. ORGANIZACIÓN DE COMPUTADORAS
descripción puede resumirse diciendo que la computadora es una máquina de Von Neumann
o máquina de programa almacenado.
En esta clase de máquinas, existe una memoria; que contiene instrucciones y datos; que como
contenidos de esa memoria, no se diferencian, salvo por la forma como son utilizados.
Estas máquinas ejecutan las instrucciones almacenadas en memoria secuencialmente, es de-
cir, procediendo desde las direcciones inferiores de la memoria hacia las superiores, leyendo y
ejecutando cada instrucción y pasando a la siguiente.
Fetch: este paso consiste en leer la próxima instrucción a ejecutarse desde la memoria.
Decode: en este paso se analiza el código binario de la instrucción para determinar qué se
debe realizar (cuál operación, con qué operandos y donde guardar el resultado).
Read: en este paso se accede a memoria para traer los operandos
Execute: es la ejecución de la operación por parte de la ALU sobre los operandos
Write: en el último paso se escribe el resultado en el destino indicado en la instrucción.
Como vimos anteriormente, dentro del procesador se encuentran los Registros. Éstos son lu-
gares de almacenamiento temporario de datos e instrucciones que se utilizan durante el cómputo.
Si en un momento dado sacamos una foto instantánea de un procesador, sus registros tendrán
un cierto conjunto de valores. Ese conjunto de valores se llama estado de la CPU. La CPU,
mientras procesa, va cambiando de estado, es decir, paso a paso va modificando los valores de
sus registros hasta llegar a un resultado de cada instrucción. Por atravesar esta sucesión de
cambios de estado, se dice que una CPU es un circuito secuencial. Los cambios de estado son
50 CAPÍTULO 6. ORGANIZACIÓN DE COMPUTADORAS
disparados por un reloj, que es un circuito auxiliar que produce pulsos o impulsos eléctricos
que hacen marchar a la CPU.
Capı́tulo 7
En este esquema del MCBE vemos los tres registros de la CPU: el PC o contador de pro-
grama, el IR o registro de instrucción, situados en la Unidad de Control, y el Acumulador,
situado en la Unidad Lógico-aritmética. Los tres son registros de ocho bits.
Además se representa la memoria, compuesta por 32 bytes de ocho bits. Las direcciones de
los bytes van, entonces, de 0 a 31. Aquı́ hemos descompuesto la memoria en trozos solamente
para poder representarla completa en el esquema, pero conviene pensar en la memoria como
una única sucesión de bytes, numerados de 0 a 31. Es costumbre, al representar los diagramas
de memoria, ubicar las posiciones con direcciones menores en la parte inferior del diagrama, y
las direcciones mayores arriba; como si la memoria fuera una escalera con posiciones numeradas
a partir de 0 y ascendiendo.
Cada combinación posible de ceros y unos en los bits de cualquiera de los registros o posiciones
de memoria representa un estado de la máquina, porque define los valores de la memoria y de los
PC IR Ac
7 15 23 31
6 14 22 30
5 13 21 29
4 12 20 28
3 11 19 27
2 10 18 26
1 9 17 25
0 8 16 24
51
52 CAPÍTULO 7. MODELO COMPUTACIONAL BINARIO ELEMENTAL
Las 32 posiciones de memoria, cada una de 8 bits, son casi todas iguales, con dos excepciones.
La posición 30 (casi al final de la memoria) está reservada para comunicación con dispo-
sitivos de entrada. Es sólo de lectura, es decir, no se pueden escribir contenidos en esa
dirección. Cuando leemos esa posición de memoria, la máquina detiene su programa y es-
pera que el usuario introduzca un dato. Una vez que el usuario ha terminado de escribirlo,
el MCBE continúa la operación del programa con el dato recién leı́do.
La posición 31 es solamente de escritura. Al escribir un dato en la dirección 31, hacemos
que el MCBE escriba ese valor por pantalla, y solamente ası́ podemos saber el resultado
de un cómputo.
Como hemos dicho, los registros son lugares de almacenamiento temporario para varios usos.
Los registros funcionan en forma parecida a la memoria, en el sentido de que se pueden leer o
escribir datos en ellos, pero están ubicados cerca del procesador y tienen tiempo de acceso mucho
más rápido que la memoria. Los registros del MCBE tienen diferentes funciones. El registro PC,
o contador de programa, contiene en cada momento la dirección de la próxima instrucción
que se va a ejecutar; es decir, contiene un número que es la dirección de la posición de memoria
donde está almacenada la instrucción que está por ejecutar el MCBE. Antes de ejecutar cada
instrucción, la CPU va a copiarla en el registro IR, o registro de instrucción; y mientras
está almacenada allı́ la instrucción, va a ser decodificada, es decir, la CPU va a interpretar de qué
instrucción se trata, y la va a ejecutar. El registro acumulador, que pertenece a la ALU, es un
registro que interviene en casi todas las operaciones del MCBE; sobre todo para las operaciones
aritméticas.
La CPU del MCBE queda definida como el conjunto de Unidad de Control con dos
registros PC e IR, más Unidad lógico-aritmética con un registro acumulador.
Esta CPU va a ser muy limitada y solamente va a ejecutar operaciones de suma y resta
en complemento a 2, con ocho bits. No va a ejecutar multiplicaciones, ni divisiones, ni
operaciones en punto flotante.
Una instrucción es una secuencia de bits (como todo!), por lo tanto debemos conocer cómo
se define el formato de la instrucción para poder interpretarla. Las instrucciones del MCBE se
codifican en ocho bits y por lo tanto pueden ser almacenadas en un byte de la memoria, o en el
registro IR (también de 8 bits). Cada instrucción se divide en dos partes:
7.2. CONJUNTO DE INSTRUCCIONES DEL MCBE 53
A su vez, los operandos pueden ser de dos clases: o bien direcciones, o bien desplaza-
mientos. Si el operando es una dirección, su valor indica la dirección de un dato. Si es un
desplazamiento, su valor indica una cantidad de posiciones que hay que saltar (en la memo-
ria) para encontrar la siguiente instrucción que hay que procesar.
Cuando el operando es una dirección, los cinco bits del operando representan una cantidad
sin signo (porque no pueden existir direcciones negativas).
Cuando es un desplazamiento, esos cinco bits son con signo, y más precisamente, en
complemento a 2; porque el desplazamiento puede ser negativo, indicando que hay que
volver hacia atrás, a una cierta dirección de la memoria a ejecutar una instrucción
que tal vez ya fue ejecutada.
Notemos que al representar las direcciones con cinco bits, sin signo, tenemos un rango de
representación de 0 a 31, justo lo que necesitamos para alcanzar todas las posiciones de memoria.
Para los desplazamientos, como estamos usando un sistema con signo, tenemos un rango de
-16 a 15. Lo que quiere decir que al trasladarnos de un lugar a otro de la memoria, vamos a
poder hacerlo en saltos de a lo sumo 16 bytes hacia atrás o 15 bytes hacia adelante.
Las instrucciones de transferencia de datos son las que leen o escriben datos en la
memoria.
Las aritméticas son las que operan entre esos datos de la memoria y el valor presente en
el registro acumulador.
Las de salto o transferencia de control, las que desvı́an, derivan o trasladan la ejecución
a otra posición de memoria.
Y las de control, completan el funcionamiento de la máquina, por ejemplo controlando
cuándo va a detenerse el programa.
Notemos que, como tenemos un campo de tres bits para definir el código de instrucción,
no vamos a poder tener más que ocho instrucciones. Precisamente hay dos instrucciones en
cada grupo de estos cuatro que hemos definido.
Instrucciones de MCBE:
000 No operación
001 Parada
010 Mem → Ac
011 Ac → Mem
100 Sumar al Ac
101 Restar al Ac
110 Salto
111 Salto cond
54 CAPÍTULO 7. MODELO COMPUTACIONAL BINARIO ELEMENTAL
Las instrucciones de transferencia de datos son dos. El código 010 copia un byte de la
memoria hacia el acumulador. Para esto se necesita la dirección de ese byte, y esa dirección
es precisamente el argumento u operando de la instrucción, y por lo tanto esa dirección está
codificada en los cinco bits de operando de la instrucción.
El código 011 es la operación inversa, es decir, copia el contenido del registro acumulador en
una posición de memoria. La dirección de esa posición está, también, determinada por los cinco
bits de operando.
En cualquiera de los dos casos, luego de ejecutarse la instrucción, el valor del PC queda
valiendo 1 más de lo que valı́a antes, es decir, se incrementa en 1. Esto permite que el ciclo de
instrucción pase a la instrucción siguiente.
El efecto sobre el estado de la máquina es exactamente lo que se describe aquı́: cambia el
valor del acumulador, en el caso de la instrucción 010, o el valor de una posición de memoria,
en el caso del código 011, y el valor del PC se incrementa en 1. No ocurre ningún otro cambio
en el estado de la máquina, ni en los registros ni en la memoria.
Las instrucciones aritméticas también son dos. Si el código es 100, la CPU va a buscar el valor
contenido en la dirección dada por el operando, y lo suma al acumulador. Es decir, se suman
el valor que tuviera anteriormente el acumulador, con el valor que proviene de esa posición de
memoria. El resultado queda en el acumulador. El valor de la posición de memoria no varı́a.
Si el código es 101, la operación es una resta, que como sabemos consiste en complementar
a 2 el operando y luego sumar. El resultado, igual que en la instrucción de suma, queda en
el acumulador, y la posición de memoria queda sin cambios. Como en las instrucciones de
transferencia de datos, el registro PC se incrementa en 1. Decimos que el PC queda apuntando
a la siguiente instrucción.
usamos la instrucción 001. El programa se detiene, y el estado final de la máquina queda con
los valores que recibieron por última vez los registros y la memoria. El valor del PC no cambia.
La operación 000 no tiene ningún efecto sobre el estado del MCBE, salvo incrementar el PC.
Ningún otro registro ni posición de memoria cambia su valor.
Ahora podemos definir el ciclo de instrucción de MCBE. MCBE siempre inicia su opera-
ción con todos los contenidos de la memoria y registros en 0, y se pone a ejecutar continuamente
el ciclo de instrucción. Para esto repite continuamente las fases siguientes.
¿Cómo es, entonces, un programa para esta máquina teórica? Es una sucesión de bytes, que
representan instrucciones y datos, contenidos en la memoria a partir de la dirección 0, y donde
cada byte va a ser interpretado como instrucción o como dato según lo diga el programa. Como
el estado inicial de la máquina es con todos los valores en 0, lo único que puede decirse con
seguridad es que la primera posición de la memoria contiene una instrucción. Pero a
partir de allı́, el desarrollo de la ejecución va a ser dado por las instrucciones particulares que
contenga el programa.
Ejemplo de Programa:
Dirección Contenido
00000 01000110
00001 10000111
00010 01101000
00011 00100000
00100
00101
00110 00001100
00111 00000001
01000
En este programa en particular, la primera instrucción es 010 00110, que es una instrucción
de transferencia de datos de la posición 6 al acumulador.
56 CAPÍTULO 7. MODELO COMPUTACIONAL BINARIO ELEMENTAL
La segunda instrucción es 100 00111, que es una suma del valor que haya en la posición 7
al acumulador.
La tercera instrucción es 011 01000, que significa transferir el valor que haya en el acumu-
lador a la posición 8.
Y la cuarta instrucción es 001 00000, que es la instrucción de parada, con lo cual termina
el programa.
Todas éstas eran las instrucciones del programa. En las posiciones 6 y 7 de la memoria
tenemos datos almacenados en complemento a 2 sobre ocho bits. Estos datos son el número
12, en la posición 6, y el número 1 en la posición 7.
En las restantes posiciones de memoria hay contenidos nulos, o sea, todos los bits en 0, y
no los escribimos para no complicar más el diagrama.
Proponemos como ejercicio examinar las siguientes frases, tomadas de exámenes de la ma-
teria, a ver si descubrimos qué está mal en cada una de ellas.
2. Lo que hacen las instrucciones de salto es cambiar el efecto de las instrucciones en los
registros del MCBE.
3. Las instrucciones de salto sirven como desplazamiento de instrucciones y cambian el orden
de los registros.
4. La instrucción de salto incondicional es un desplazamiento sin signo, la de salto condicional
es un desplazamiento con signo.
5. Las instrucciones de salto copian el contenido de la dirección en el acumulador.
58 CAPÍTULO 7. MODELO COMPUTACIONAL BINARIO ELEMENTAL
Capı́tulo 8
El Software
En el capı́tulo anterior hemos visto un cómo escribir un programa para la MCBE. El lenguaje
utilizado, la secuencia de 8 bits que representaban instrucciones o datos es el llamado lenguaje
de máquina del MCBE.
Por supuesto, escribir un programa para el MCBE y depurarlo, es decir, identificar y corregir
sus errores, es una tarea muy dificultosa, porque los códigos de operación, las direcciones y los
datos, fácilmente terminan confundiéndonos. Para facilitar la programación, se ha definido un
lenguaje alternativo llamado el ensamblador del MCBE.
En lugar de códigos de tres bits usamos unas abreviaturas un poco más significativas
(llamadas los mnemónicos de las instrucciones).
En lugar de direcciones de cinco bits para los datos, usamos unos nombres simbólicos
(rótulos o etiquetas) que hacen referencia a esas direcciones.
Para las instrucciones de salto, en lugar de desplazamientos, también usamos rótulos o
etiquetas para indicar la instrucción del programa adonde deseamos saltar.
Cada CPU del mundo real tiene su propio lenguaje de máquina, y aunque mucho más
poderosos y de instrucciones más complejas, se parecen bastante, en lı́neas generales, al lenguaje
de máquina del MCBE. Igual que ocurre con el lenguaje de máquina, cada CPU del mundo real
tiene su propio lenguaje ensamblador, basado en los mismos principios que el que mostramos
aquı́.
El lenguaje de máquina de cualquier CPU y su lenguaje ensamblador (o Assembler ), son
llamados en general lenguajes de bajo nivel.
59
60 CAPÍTULO 8. EL SOFTWARE
Mnemónicos
Rótulos
Cuando necesitamos hacer referencia a una dirección, como en las operaciones de transferen-
cia o en las aritméticas, el ensamblador nos permite independizarnos del valor de esa dirección y
simplemente indicar un nombre simbólico o rótulo para esa dirección. Ası́, un rótulo equivale
en lenguaje ensamblador a la dirección de un dato.
Para que el programa quede completo, ese nombre simbólico debe aparecer en algún lugar
del programa, al principio de la instrucción, y separado por un carácter : del resto de la lı́nea.
Ejemplo
En este ejemplo, SIGUE, FIN, UNO y CANT son rótulos. El rótulo CANT, por ejemplo, nos
permite referirnos en la primera instrucción, a un dato declarado más adelante con ese nombre.
Del mismo modo, cuando la instrucción es de salto, podemos hacer referencia a la posición de
memoria donde se hará el salto usando un rótulo, como en la quinta instrucción, JMP SIGUE.
Es importante recordar que, de todas maneras, en la traducción de ensamblador a lenguaje de
máquina para las instrucciones de salto, el rótulo se sustituye por un desplazamiento, y
no por una dirección.
Ejemplo
Rótulos predefinidos
Ensambladores
Como hemos dicho anteriormente, una CPU como el MCBE sólo sabe ejecutar instrucciones
de código máquina (expresadas con unos y ceros). Vimos también que el lenguaje ensamblador
es una versión legible de las instrucciones de máquina. Ahora bien, si escribimos el programa en
lenguaje ensamblador, ¿cómo hacemos para que la máquina lo ejecute? Podemos pensar en un
programa que automáticamente traduzca de un lenguaje a otro. A este programa se le conoce
como ensamblador o assembler. Un ensamblador es un programa traductor. Los traductores
traducen programas de un lenguaje a otro.
Como es de imaginar, los procesadores de familias diferentes tienen conjuntos de instruc-
ciones diferentes. Ası́, un lenguaje y un programa ensamblador están ligados a un procesador
determinado. El código máquina producido por un ensamblador no puede ser trasladado a otro
procesador que no sea aquel para el cual fue ensamblado. Las instrucciones de máquina tendrán
sentidos diferentes para uno y otro.
Como vemos, tanto el lenguaje de máquina como el ensamblador o Assembler son lenguajes
orientados a la máquina. Ofrecen control total sobre lo que puede hacerse con un procesa-
dor o con el sistema construido alrededor de ese procesador. Por este motivo son elegidos para
proyectos de software donde se necesita dialogar estrechamente con el hardware, como ocurre
con los sistemas operativos. Estos lenguajes tan ligados a un procesador determinado, requieren
conocimiento profundo de dicho procesador. Escribir un programa para resolver un problema
complejo en un lenguaje de bajo nivel suele ser muy costoso en tiempo y esfuerzo. Estos pro-
gramas además son poco portables, es decir, no pueden ejecutarse en otro procesador diferente
sin re-escribir código.
Ensamblador x86
Cada CPU tiene su propio lenguaje ensamblador, y sus propios programas traductores (en-
sambladores). Por ejemplo, la familia de procesadores de Intel para computadoras personales
comparte el mismo ISA o arquitectura (conjunto de instrucciones). Cualquiera de estos proce-
sadores puede ser programado usando un ensamblador de la familia x86. Los procesadores de
la familia x86 se encuentran en casi todas las computadoras personales y notebooks.
Según la tradición, el primer programa que uno debe intentar escribir cuando comienza a
aprender un lenguaje de programación nuevo es Hola mundo. Es un programa que simplemente
escribe esas palabras por pantalla. Aquı́ mostramos el clásico ejemplo de Hola mundo en el
lenguaje ensamblador de la familia x86.
Ejemplo programa ensamblador familia x86
.globl _start
.text # seccion de codigo
_start:
movl $len, %edx # carga parametros longitud
movl $msg, %ecx # y direccion del mensaje
movl $1, %ebx # parametro 1: stdout
62 CAPÍTULO 8. EL SOFTWARE
Ensamblador ARM
El ARM es un procesador que suele encontrarse en plataformas móviles como tablets o teléfo-
nos celulares, porque ha sido diseñado para minimizar el consumo de energı́a, una caracterı́stica
que lo hace ideal para construir esos productos portátiles.
¿Podremos ejecutar el código máquina producido por un ensamblador para x86 en una
computadora basada en otro procesador, como por ejemplo ARM? La respuesta es no. El progra-
ma en lenguaje ensamblador deberı́a ser portado o traducido al ensamblador propio de ARM,
por una persona programadora, y luego ensamblado con un ensamblador para ARM.
Ejemplo programa ensamblador familia ARM
.global main
main:
@ Guarda la direccion de retorno lr
@ mas 8 bytes para alineacion
push {ip, lr}
@ Carga la direccion de la cadena y llama syscall
ldr r0, =hola
bl printf
@ Retorna 0
mov r0, #0
@ Desapila el registro ip y guarda
@ el siguiente valor desapilado en el pc
pop {ip, pc}
hola:
.asciz "Hola, mundo!\n"
Ensamblador PowerPC
Lo mismo ocurre con otras familias de procesadores como el PowerPC, un procesador que
fue utilizado para algunas generaciones de consolas de juegos, como la PlayStation 3.
Ejemplo programa ensamblador familia PowerPC
_start:
li 0,4 # syscall sys_write
li 3,1 # 1er arg: desc archivo (stdout)
# 2do arg: puntero a mensaje
lis 4,msg@ha # carga 16b mas altos de &msg
addi 4,4, msg@l # carga 16b mas bajos de &msg
li 5,len # 3er arg: longitud de mensaje
sc # llamada al kernel
#
li 0,1 # syscall sys_exit
li 3,1 # 1er arg: exit code
sc # llamada al kernel
Para facilitar la programación (en los casos que no es necesario programar en bajo nivel)
existen lenguajes de alto nivel. Estos lenguajes ocultan a la programadora los detalles de
la arquitectura de las computadoras y le facilitan la programación de problemas de software
complejos. Son más orientados al problema, lo que quiere decir que nos aı́slan de cómo
funcionan los procesadores o de cómo se escriben las instrucciones de máquina, y nos permiten
especificar las operaciones que necesitamos para resolver nuestro problema en forma más parecida
al lenguaje natural, matemático, o humano. Una ventaja adicional de los lenguajes de alto nivel
es que resultan más portables, y su depuración (el proceso de corregir errores de programación)
es mucho más fácil.
Compiladores: Producen una versión en código máquina del programa fuente. Este pro-
grama resultante puede ejecutarse (n cantidad de veces) sin necesidad de compilar cada
vez.
Intérpretes: Alternan las fases de traducción y ejecución, por lo cual la ejecución completa
del mismo programa tardará algo más de tiempo. Traducen cada linea y la ejecutan cada
vez que se ejecuta el programa. El programa interpretado debe ser traducido cada vez que
se ejecute.
Al igual que el compilador, el intérprete traduce un programa fuente escrito en algún lenguaje
de alto nivel, pero con la diferencia que cada instrucción es ejecutada inmediatamente, sin generar
un programa en lenguaje de máquina.
Velocidad de ejecución
Portabilidad
Ciclo de compilación
Quien programa necesita producir un archivo ejecutable y para ello utilizará varios programas
de sistema como editores, traductores, vinculadores. Por otro lado, hará llamadas a funciones
de biblioteca. Las bibliotecas consisten en versiones objeto de varias funciones, compiladas,
y reunidas con un programa bibliotecario, en un archivo. Esa biblioteca es consultada por el
vinculador para completar las referencias pendientes del archivo objeto. El resultado final del
ciclo de compilación es un ejecutable. La figura 8.2 muestra un esquema del ciclo.
Resumiendo:
8.2. LENGUAJES DE ALTO NIVEL 65
Sistemas Operativos
En este capı́tulo veremos de qué manera evolucionó el software de base asociado a los sistemas
de cómputo de diferentes momentos históricos hasta llegar a los actuales sistemas operativos.
Un sistema operativo es un software cuya función principal es la de ser intermediario entre
las personas usuarias y el hardware del sistema de cómputo.
Las primeras computadoras estaban dedicadas a una única tarea, perteneciente a una única
persona usuaria. Podı́an ser utilizadas por diferentes usuarixs, pero cada unx debı́a esperar su
turno para reprogramarlas manualmente, lo cual era laborioso y se llevaba gran parte del tiempo
por el cual esos usuarixs pagaban.
Una vez que se popularizaron las máquinas de programa almacenado, se pudo minimizar el
tiempo ocioso que presentaban los sistemas de cómputo anteriores, adoptando esquemas de
carga automática de trabajos. Un trabajo tı́pico consistı́a en la compilación y ejecución de un
programa, o la carga de un programa compilado más un lote de datos de entrada, y la impresión
de un cierto resultado de salida del programa. Estos trabajos estaban definidos por conjuntos o
lotes de tarjetas perforadas, de ahı́ su nombre de trabajos por lotes o, en inglés, batch.
Una vez que llegó la posibilidad de tener varios programas coexistiendo simultáneamente en
la memoria, se buscó que la conmutación del uso del procesador entre ellos fuera tan rápida, que
pareciera que cada programa funcionaba sin interrupciones. Aunque el sistema era de tiempo
67
68 CAPÍTULO 9. SISTEMAS OPERATIVOS
¿Cuáles son los cinco momentos evolutivos del software de base que reconocemos?
¿A qué se llama un trabajo batch o lote de trabajo? ¿Qué es un archivo batch en el
mundo de la computación personal?
¿Cuál fue la necesidad que impulsó la creación de sistemas batch?
¿Cuál fue la necesidad que impulsó la creación de sistemas multiprogramados?
¿Cuál fue la necesidad que impulsó la creación de sistemas de tiempo compartido?
Los modernos sistemas operativos tienen varios componentes bien diferenciados. Los sistemas
operativos de propósito general normalmente se presentan en una distribución que contiene
e integra al menos tres componentes.
Interfaz de usuario: También se encuentra junto a este software del sistema alguna forma
de interfaz de usuario, que puede ser gráfica o de caracteres. Esta interfaz de usuario se
llama en general shell, especialmente cuando la interfaz es un procesador de comandos,
basado en caracteres, y los comandos se tipean.
Hay algunas excepciones a esta estructura de componentes, por ejemplo, en los sistemas
operativos empotrados o embebidos (embedded systems), que están ligados a un dispositivo
especial y muy especı́fico, como es el caso de algunos robots, instrumental médico, routers, elec-
trodomésticos avanzados, etc. Estos sistemas operativos constan de un kernel que tiene la misión
9.3. KERNEL DEL SO 69
de hacer funcionar cierto hardware especial, pero no necesariamente incluyen una interfaz de
usuario (porque el usuario no necesita en realidad comunicarse directamente con ellos) o no in-
cluyen software de sistema porque sus usuarios no son quienes se encargan de su mantenimiento.
Por otro lado, un tı́pico sistema operativo multipropósito debe dar soporte entonces a la
actividad de una gran variedad de aplicaciones. No solamente a la interfaz de usuario o procesador
de comandos, más el software de sistema incluido, sino también a toda la gama de aplicaciones
que desee ejecutar el usuario, como programas de comunicaciones (navegadores, programas de
transferencia de archivos, de mensajerı́a); aplicaciones de desarrollo de programas (compiladores,
intérpretes de diferentes lenguajes), etc.
Si los procesos de usuarix pudieran utilizar directamente los recursos en cualquier momento
y sin coordinación, los resultados podrı́an ser desastrosos. Por ejemplo, si dos o más programas
quisieran usar la impresora al mismo tiempo, en el papel impreso se verı́a una mezcla de las
salidas de los programas que no servirı́a a ninguno de ellos. Como el sistema operativo debe
coordinar el acceso de los diferentes procesos a esos recursos, resulta necesario que cuente con
alguna forma de imponer conductas y lı́mites a esxs usuarixs y programas, para evitar que algunx
tome control del sistema en perjuicio de lxs demás. Para garantizarle este poder por sobre lxs
usuarixs, el sistema operativo requiere apoyo del hardware: su código se ejecuta en un modo
especial de operación del hardware, el modo privilegiado del procesador.
Los modernos procesadores funcionan en lo que llamamos modo dual de ejecución, donde
el ISA se divide en dos grupos de instrucciones:
El kernel ofrece su capacidad de control de todos los recursos a los procesos o programas
en ejecución, quienes le solicitan determinadas operaciones sobre esos recursos. Por ejemplo,
70 CAPÍTULO 9. SISTEMAS OPERATIVOS
Si se cumplen todos los requisitos, se ejecutará el servicio pedido y luego se volverá a modo
no privilegiado, a continuar con la ejecución del proceso.
Por ejemplo, el sistema de archivos diseñado para el sistema operativo CP/M de la empresa
Digital, en los años 70, fue adaptado para el MS-DOS de Microsoft, cuya evolución final
fue Windows.
Los diseñadores de Windows NT fueron los mismos que construyeron el sistema operativo
VMS de los equipos VAX, también de Digital, y aportaron su experiencia. De hecho,
9.5. SERVICIOS DEL SO 71
Otra importante lı́nea genealógica es la que relaciona el antiguo Multics, por un lado, con
Unix y con Linux; y más recientemente, con el sistema para plataformas móviles Android.
Unix fue el primer sistema operativo escrito casi totalmente en un lenguaje de alto nivel,
el C, lo cual permitió portarlo a diferentes arquitecturas. Esto le dio un gran impulso y la
comunidad cientı́fica lo adoptó como el modelo de referencia de los sistemas operativos de
tiempo compartido.
En 1991 Linus Torvalds lanzó un proyecto de código abierto dedicado a la construcción
de un sistema operativo compatible con Unix pero sin hacer uso de ningún código ante-
riormente escrito, lo que le permitió liberarlo bajo una licencia libre. La consecuencia es
que Linux, su sistema operativo, rápidamente atrajo la atención de centenares de desa-
rrolladores de todo el mundo, que sumaron sus esfuerzos para crear un sistema que fuera
completo y disponible libremente.
Linux puede ser estudiado a fondo porque su código fuente no es secreto, como en el caso de
los sistemas operativos propietarios. Esto lo hace ideal, entre otras cosas, para la enseñanza
de las Ciencias de la Computación. Esta cualidad de sistema abierto permitió que otras
compañı́as lo emplearan en muchos otros proyectos.
Otros sistemas operativos han cumplido un ciclo con alguna clase de final, al no superar la
etapa experimental, haberse transformado definitivamente en otros sistemas, desaparecer
del mercado o quedar confinados a cierto nicho de aplicaciones. Algunos, por sus objetivos
de diseño, son menos visibles, porque están destinados a un uso que no es masivo, como
es el caso del sistema de tiempo real QNX.
Después de conocer estas cuestiones generales sobre los sistemas operativos, veremos con un
poco más de detalle los diferentes servicios provistos por los principales subsistemas de un SO:
Gestión de procesos
Gestión de memoria
Gestión de archivos
Operaciones de Entrada/Salida
Protección
Creación de procesos
Cada proceso pasará por varios estados durante su vida. Básicamente, una vez creado el
proceso pasa a estar en estado listo, cuando el sistema operativo le asigna el procesador a ese
proceso, pasa a estado ejecutando, cuando el proceso realiza una operación de entrada/salida
pasa a estado en espera.
Cuando recién se crea un proceso, su estado es listo, porque está preparado para recibir
la CPU cuando el planificador o scheduler lo disponga.
En algún momento recibirá la CPU y pasará a estado ejecutando.
El proceso en algún momento requerirá servicios del SO (por ejemplo, para operaciones de
entrada/salida, como recibir datos por el teclado o por la red, imprimir resultados, etc.).
Durante estas operaciones de entrada/salida, el proceso no utilizará la CPU para realizar
cómputos, sino que deberá esperar el final de este servicio del SO. Como las operaciones
de entrada/salida son mucho mas lentas (por varias magnitudes) que la velocidad en que
la CPU procesa instrucciones, el sistema pone en estado de espera al proceso hasta que
finalice la operación de entrada/salida.
Mientras tanto, como la CPU ha quedado libre, el SO aprovecha la oportunidad de darle
la CPU a algún otro proceso que esté en estado listo.
Cuando finalice una operación de entrada/salida que ha sido requerida por un proceso,
este proceso volverá al estado de listo y esperará que algún otro proceso libere la CPU
para volver a ejecutando.
Al volver al estado ejecutando, el proceso retomará la ejecución desde la instrucción
inmediatamente posterior a la que solicitó el servicio del SO.
En algún momento, el proceso ejecutará la última de sus instrucciones y finalizará. El SO
libera los recursos que utilizó para su gestión.
9.5. SERVICIOS DEL SO 73
Figura 9.2: Primer proyecto que implementó un sistema de tiempo compartido (1957) IBM 704
modificado.
Como vimos en la subsección 9.1.4, los sistemas de tiempo compartido están diseñados
para ser interactivos, y tienen la misión de hacer creer a cada usuarix que el sistema de cómputo
está dedicado exclusivamente a sus procesos. Sin embargo, normalmente existen muchı́simos
procesos activos simultáneamente en un SO de propósito general. Para lograr esto el planificador
de estos SO debe ser capaz de hacer los cambios de estado con mucha velocidad. El resultado es
que lxs usuarixs prácticamente no perciben estos cambios de estado. En un sistema de tiempo
compartido, el ciclo de estados de los procesos es similar al del sistema multiprogramado, pero
con una importante diferencia.
Notemos que los diagramas de estados del sistema multiprogramado y del sistema de
tiempo compartido se diferencian sólo en una transición: la que lleva del estado de ejecutando
al de listo en este último sistema.
¿Por qué un proceso que ejecuta una solicitud de entrada/salida no pasa directamente al
estado de listo?
¿En qué radica la diferencia entre el scheduling de un sistema multiprogramado y el de un
sistema de tiempo compartido?
Si en un sistema multiprogramado se ejecuta un programa escrito de forma que nunca
ejecuta una operación de entrada/salida, ¿liberará alguna vez la CPU durante su vida?
¿Y en un sistema de tiempo compartido?
Concurrencia y paralelismo
Cuando el sistema de cómputo tiene más de una CPU, entonces podemos tener dos
o más procesos en estado de ejecución simultáneamente, y entonces decimos que esos
procesos son paralelos.
Comandos Linux
Monitorización de procesos
Los sistemas operativos suelen ofrecer herramientas para monitorizar o controlar los procesos
del sistema.
Comando top
En Linux, el comando top ofrece una vista de los procesos, información acerca de los recursos
que están ocupando, y algunas estadı́sticas globales del sistema. Es conveniente consultar el
manual del comando (man top) para investigar a fondo los significados de cada uno de los datos
presentados en pantalla.
Estadı́sticas globales
En el cuadro superior, top muestra:
• De nice o de cortesı́a.
• Ocioso
• De espera
• Tiempos imputables a interrupciones
Estadı́sticas de memoria RAM total, usada y libre, y ocupada por buffers de entrada/salida
Estadı́sticas de espacio de intercambio o swap total, usado y libre.
Estadı́sticas de procesos
Para cada proceso, el programa top muestra:
El comando top tiene muchas opciones y comandos interactivos. Uno de ellos muestra los
datos de sistema desglosados por CPU o unidad de ejecución.
Comandos de procesos
Interesante
Administración de procesos
Prioridades de ejecución de procesos
última vez, qué usuarios tienen permisos para ejecutar qué acciones con cada uno de ellos, etc.
Como todos estos datos son acerca de los archivos, y no tienen nada que ver con los datos
contenidos en los archivos, son llamados metadatos. El sistema de archivos o filesystem
mantiene tablas y listas de metadatos que describen los archivos contenidos en un medio de
almacenamiento.
Una caracterı́stica compartida por la mayorı́a de los sistemas de archivos es la organización
jerárquica de los archivos en estructura de directorios. Los directorios son contenedores de ar-
chivos (y de otros directorios). Los directorios han sido llamados, en la metáfora de las interfaces
visuales de usuario, carpetas.
En rigor de verdad, el nombre de sistema de archivos o filesystem designa varias cosas,
relacionadas pero diferentes:
Árbol de directorios
Por ejemplo, el directorio raı́z, donde se origina toda la jerarquı́a de directorios, tiene el
nombre especial /.
El directorio lib (abreviatura de library o biblioteca) contiene bibliotecas de software.
Los directorios bin, sbin. /usr/bin, etc., contienen archivos ejecutables (a veces llamados
binarios).
Los nombres completos, o referencias absolutas, de los archivos y directorios se dan indi-
cando cuál es el camino que hay que recorrer, para encontrarlos, desde la raı́z del sistema de
archivos.
9.5. SERVICIOS DEL SO 77
Ejemplo
La referencia absoluta para el archivo texto.txt ubicado en el directorio juan, que está dentro
del directorio home, que está dentro del directorio raı́z, es /home/juan/texto.txt.
Una referencia relativa, por otro lado, es una forma de mencionar a un archivo que depende
de dónde está situado el proceso o usuario que quiere utilizarlo. Todo proceso, al ejecutarse, tiene
una noción de lugar del filesystem donde se encuentra.
Comandos Linux
Al iniciar un shell, el directorio actual es el directorio home, que es el espacio privado del
usuario. Éste es el directorio actual del proceso shell.
Para cambiar de directorio se usa el comando $cd directorio destino.
El comando pwd dice cuál es el directorio actual de un shell.
La referencia relativa de un archivo indica cuál es el camino que hay que recorrer para
encontrarlo desde el directorio actual del proceso. Para el mismo archivo del ejemplo anterior,
si el directorio activo del shell es /home/juan, la referencia relativa será simplemente texto.txt.
La referencia es relativa porque, si el proceso cambia de directorio activo, ya no servirá como
referencia para ese mismo archivo.
$ ls -l util
total 60
-rwxr-xr-x 1 oso oso 40 Apr 18 16:54 github
-rw-r--r-- 1 oso oso 1337 May 4 12:11 howto.txt
-rwxrwxr-x 1 oso oso 458 Feb 9 16:28 macro
drwxr-xr-x 2 oso oso 4096 May 26 18:14 prueba
-rwxr-xr-x 1 oso oso 30 Feb 9 16:28 server
Tipo de archivo
El primer elemento de cada fila contiene un carácter que indica el tipo del archivo, y los
siguientes caracteres indican los permisos asignados al archivo. El tipo indicado por el guión es
archivo regular, y el indicado por la letra d es directorio. En el ejemplo, todos los archivos
son regulares salvo prueba, que es un directorio. Otros tipos de archivo tienen otros caracteres
indicadores.
Permisos
Los permisos de cada archivo están indicados por los nueve caracteres siguientes hasta el
espacio. Para interpretarlos, se separan en tres grupos de tres caracteres. Los primeros tres
caracteres indican los permisos que tiene el usuario dueño del archivo; los siguientes tres, los
permisos para el grupo al cual pertenece el archivo; y los últimos tres, los permisos que tienen
otros usuarios.
Cada grupo de permisos indica si se permite la lectura, escritura, o ejecución del archivo.
Una letra r en el primer lugar del grupo indica que el archivo puede ser escrito. Una w en
el segundo lugar, que puede ser escrito o modificado. Una x en el tercer lugar, que puede ser
ejecutado. Cuando no existen estos permisos, aparece un carácter guión.
78 CAPÍTULO 9. SISTEMAS OPERATIVOS
Ası́, el archivo github del ejemplo tiene permisos rwxr-xr-x, que se separan en permisos
rwx para el dueño (el dueño puede leerlo, escribirlo o modificarlo, y ejecutarlo), r-x para
el grupo (cualquier usuario del grupo puede leerlo y ejecutarlo), y lo mismo para el resto
de los usuarios.
Por el contrario, el archivo howto.txt tiene permisos rw-r–r–, que se separan en permisos
rw- para el dueño (el dueño puede leerlo, escribirlo o modificarlo, pero no ejecutarlo), r–
para el grupo (cualquier usuario del grupo puede leerlo, pero no modificarlo ni ejecutarlo),
y lo mismo para el resto de los usuarios.
Cuenta de links
La cuenta de links es la cantidad de nombres que tiene un archivo.
Dueño y grupo
Las columnas tercera y cuarta indican el usuario y grupo de usuarios al cual pertenece el
archivo.
Tamaño
Aparece el tamaño en bytes de los archivos regulares.
Fecha y hora
Aparecen la fecha y hora de última modificación de cada archivo.
Nombre
El último dato de cada lı́nea es el nombre del archivo.
Bloques de disco
El SO ve los discos como un vector de bloques o espacios de tamaño fijo. Cada bloque se
identifica por su número de posición en el vector, o dirección de bloque. Esta dirección es
utilizada para todas las operaciones de lectura o escritura en el disco.
Cuando el SO necesita acceder a un bloque para escribir o leer sus contenidos, envı́a un
mensaje al controlador del disco especificando su dirección.
Si la operación es de lectura, además indica una dirección de memoria donde desea recibir
los datos que el controlador del disco leerá.
Si la operación es de escritura, indica una dirección de memoria donde están los datos que
desea escribir.
En un sistema multiprogramado, la memoria debe ser dividida de alguna forma entre los
procesos que existen simultáneamente en el sistema. La tarea de controlar qué proceso recibe
qué región de memoria, o gestión de memoria, es un problema con varias soluciones.
Mapa de memoria
Para que este programa pueda convertirse en un proceso, tanto instrucciones como datos
deben estar almacenados en posiciones de memoria principal. Solamente de allı́ pueden ser
leı́dos por el procesador. Además, los procesos requieren otros espacios de memoria para otros
usos.
Todos estos componentes forman lo que a veces se llama mapa de memoria de cada proceso,
y requieren memoria fı́sica.
Espacios de direcciones
La memoria fı́sica del sistema se ve como un arreglo, vector o secuencia ordenada de celdas o
posiciones de almacenamiento. Cada posición tiene una dirección que es el número con el que
se la puede acceder para leer o escribir su contenido. En un sistema de cómputo, el conjunto de
direcciones de la memoria fı́sica es un espacio de direcciones fı́sicas.
Traducción de direcciones
Para que las referencias a direcciones lógicas conserven el sentido deseado por el programa-
dor, el sistema utiliza alguna forma de traducción de direcciones. Las referencias a direcciones
generadas por el procesador pertenecerán al espacio lógico del proceso; pero el mecanismo de
traducción de direcciones mapeará esas direcciones lógicas a las direcciones fı́sicas asignadas.
00000 LD DATO
00001 ADD CANT
00010 ST SUMA
00011 HLT
00100 DATO: 10
00101 CANT: 1
00110 SUMA: 0
En este ejemplo, DATO, CANT y SUMA son las posiciones de memoria 4, 5 y 6. Si este
programa se carga en la posición cero de la memoria fı́sica, los espacios fı́sico y lógico coincidirán.
Sin embargo, en un sistema multiprogramado, es posible que el proceso reciba otras posiciones
de memoria fı́sica. Por ejemplo, el programa podrı́a haber sido cargado a partir de la dirección
20 de la memoria. Entonces, la posición de memoria fı́sica donde residirá el valor SUMA no es
la posición 6, sino la 26.
El mecanismo de traducción de direcciones del sistema deberá sumar el valor base de la
memoria (en este caso, 20) a todas las referencias a memoria generadas por el proce-
sador para mantener el funcionamiento deseado. Sin traducción de direcciones, la instrucción
ST SUMA almacenará el resultado en la posición cuya dirección fı́sica es 6. . . ¡que pertenece a
otro proceso!
Uno de los esquemas de asignación de memoria más simples consiste en asignar una región de
memoria contigua (un conjunto de posiciones de memoria sin interrupciones) a cada proceso.
Si un SO utiliza este esquema de asignación de memoria, establece particiones de la memo-
ria, de un tamaño adecuado a los requerimientos de cada proceso. Cuando un proceso termina,
su región de memoria se libera y puede ser asignada a un nuevo proceso.
9.5. SERVICIOS DEL SO 81
Fragmentación externa
El problema de este esquema es que, a medida que el sistema opere, las regiones que queden
libres pueden ser tan pequeñas que un proceso nuevo no pueda obtener una región de tamaño
suficiente, a pesar de que exista memoria libre en cantidad suficiente en el sistema. Este
fenómeno se llama fragmentación externa.
El problema de este esquema es que, a medida que el sistema opere, las regiones que queden
libres pueden ser tan pequeñas que un proceso nuevo no pueda obtener una región contigua
de tamaño suficiente, a pesar de que exista memoria libre en cantidad suficiente en el
sistema. Este fenómeno se llama fragmentación externa.
Un remedio para la fragmentación externa es la compactación de la memoria, es decir,
reubicar los procesos que estén ocupando memoria, de manera de que sus regiones sean contiguas
entre sı́. De esta forma los “huecos” en la memoria se unen y se crean regiones libres contiguas
grandes.
El problema con esta solución es que la reubicación de los procesos es muy costosa en tiempo.
Mientras el sistema esté compactando la memoria, los procesos que estén siendo reubicados no
podrán realizar otra tarea, y el sistema perderá productividad.
Esta clase de cargas extra en tareas administrativas, que quitan capacidad al sistema para
atender el trabajo genuino, se llama sobrecarga u overhead.
9.5.5. Segmentación
9.5.6. Paginación
Fragmentación interna
Bajo este esquema no hay fragmentación externa, porque, si existe espacio libre, siempre será
suficiente para alojar al menos una página. Sin embargo, en general, el tamaño del espacio lógico
del proceso no es exactamente divisible por el tamaño de la página; por lo tanto, puede haber
algún espacio desaprovechado en las páginas asignadas. Esta condición se llama fragmentación
interna.
Tabla de páginas
Para poder mantener la correspondencia entre marcos de memoria y páginas de los procesos,
el SO mantiene una tabla de páginas por cada proceso.
La tabla de páginas de cada proceso dice, para cada página del proceso, qué marco le ha
sido asignado, además de otra información de control.
La tabla de páginas puede contener referencias a marcos compartidos con otros procesos.
Esto hace posible la creación de regiones de memoria compartida entre procesos.
Debido a que los programas no utilizan sino una pequeña parte de su espacio lógico en cada
momento (fenómeno llamado localidad de referencias), la asignación por paginación tiene
una propiedad muy interesante: no es necesario que todas las páginas de un proceso estén en
memoria fı́sica para que pueda ser ejecutado.
Esto permite la creación de sistemas con paginación por demanda, donde las páginas se
cargan en memoria a medida que se necesitan. Un proceso puede empezar a ejecutarse apenas
esté cargada la primera de sus páginas en memoria, sin necesidad de esperar a que todo su
espacio lógico tenga memoria fı́sica asignada.
Cada proceso demanda al SO la carga de una página de su espacio lógico al espacio fı́sico
en el momento en que referencia algún objeto perteneciente a esa página. De esta manera la
actividad de entrada/salida desde el disco a la memoria se reduce al mı́nimo necesario.
Utilizando 1) paginación por demanda, 2) agregando algunas caracterı́sticas al mecanismo
de traducción de direcciones, y 3) contando con un espacio de almacenamiento extra en disco
para intercambio de páginas o swapping, se puede implementar un sistema de memoria
virtual. La mayorı́a de los SO multipropósito para hardware con MMU utiliza esta técnica.
Podemos ejecutar más procesos de los que cabrı́an en memoria fı́sica si debiéramos
asignar todo el espacio lógico de una vez.
Los procesos pueden tener un tamaño de espacio lógico más grande de lo que permite el
tamaño de la memoria fı́sica.
9.5. SERVICIOS DEL SO 83
Bit de validez
Indica si la página del proceso tiene memoria fı́sica asignada.
Bit de modificación
Indica si la página ha sido modificada desde que se le asignó memoria fı́sica.
El bit de validez de cada página indica si la página tiene o no asignado un marco, y es crucial
para el funcionamiento del sistema de memoria virtual. Cuando la CPU genera una referencia a
una página no válida, la condición que se produce se llama un fallo de página (page fault)
y se resuelve asignando un marco, luego de lo cual el proceso puede continuar.
Además de estos bits de validez y modificación, la tabla de páginas contiene datos sobre los
permisos asociados con cada página.
El mecanismo de memoria virtual funciona de la siguiente manera:
Cada dirección virtual tiene un cierto conjunto de bits que determinan el número de página.
Los bits restantes determinan el desplazamiento dentro de la página.
Cuando un proceso emite una referencia a una dirección virtual, la MMU extrae el número
de página de la dirección y consulta la entrada correspondiente en la tabla de páginas.
Si la información de control de la tabla de páginas dice que este acceso no es permitido,
la MMU provoca una condición de error que interrumpe el proceso.
Si el acceso es permitido, la MMU computa la dirección fı́sica reemplazando los bits de
página por los bits de marco.
Si el bit de validez está activo, la página ya está en memoria fı́sica.
Si el bit de validez no está activo, ocurre un fallo de página, y se debe asignar un marco.
Se elige un marco de una lista de marcos libres, se lo marca como utilizado y se completa
la entrada en la tabla de páginas. Los contenidos de la página se traerán del disco.
La MMU entrega la dirección fı́sica requerida al sistema de memoria.
Si la operación era de escritura, se marca la página como modificada.
Reemplazo de páginas
Cuando no existan más marcos libres en memoria para asignar, el SO elegirá una página
vı́ctima del mismo u otro proceso y la desalojará de la memoria. Aquı́ es donde se utiliza el bit
de modificación de la tabla de páginas.
Posteriormente, en algún otro momento, el proceso dueño de esta página querrá accederla.
La MMU verificará que la página no es válida y disparará una condición de fallo de página. La
página será traı́da del espacio de intercambio, en el estado en que se encontraba al ser desalojada,
y el proceso podrá proseguir su ejecución.
Ejemplo
Supongamos un sistema donde existen dos procesos activos, con algunas páginas en memoria
principal, y una zona de intercambio en disco.
84 CAPÍTULO 9. SISTEMAS OPERATIVOS
El proceso P1 tiene asignadas cuatro páginas (de las cuales sólo la página 2 está presente
en memoria principal), y P2, dos páginas (ambas presentes). Hay tres marcos libres (M4,
M6 y M7) y la zona de intercambio está vacı́a.
P1 recibe la CPU y en algún momento ejecuta una instrucción que hace una referencia a
una posición dentro de su página 3 (que no está en memoria).
Ocurre un fallo de página que trae del almacenamiento la página 3 de P1 a un marco libre.
La página 3 se marca como válida en la tabla de páginas de P1.
Como antes, ocurre un fallo de página, se trae la página 2 de P3 del disco, y se copia en
un marco libre. Se marca la página 2 como válida y P3 continúa su ejecución haciendo
una referencia a una dirección que queda dentro de su página 3.
Se resuelve como siempre el fallo de página para la página 3 y P3 hace una nueva referencia
a memoria, ahora a la página 4.
Pero ahora la memoria principal ya no tiene marcos libres. Es el momento de elegir una
página vı́ctima para desalojarla de la memoria. Si la página menos recientemente usada es
la página 2 de P1, es una buena candidata. En caso de que se encuentre modificada desde
que fue cargada en memoria, se la copia en la zona de intercambio para no perder esas
modificaciones, y se declara libre el marco M2 que ocupaba.
Se marca como no válida la página que acaba de salir de la memoria principal. La próxima
referencia a esta página que haga P1 provocará un nuevo fallo de página.
Se copia la página que solicitó P3 en el nuevo marco libre, se la marca como válida en la
tabla de páginas de P3, y el sistema continúa su operación normalmente.
Notemos que en este ejemplo existen tres procesos cuyos tamaños de espacio lógico miden 4,
5 y 6 páginas, dando un total de 15 páginas. Sin embargo, el sistema de cómputo sólo tiene
ocho marcos.
Sin paginación por demanda y memoria virtual, solamente podrı́a entrar en el sistema uno
de los tres procesos. Durante las operaciones de entrada/salida de ese proceso, la CPU quedarı́a
desaprovechada. Además, si alguno de los procesos tuviera un espacio lógico de más de ocho
páginas, no podrı́a ser ejecutado.
Con la técnica de memoria virtual, los tres procesos pueden estar activos simultáneamente en
el sistema, aumentando la utilización de CPU. Y, si alguno de esos procesos tuviera un espacio
lógico de más de 8 páginas, el sistema seguirı́a funcionando del mismo modo.
Capı́tulo 10
Redes de computadoras
Una red cuyos lı́mites (o diámetro) son pequeños, se llama una red de área local o
LAN (Local Area Network). Tı́picamente, una LAN está contenida en una oficina,
piso o edificio.
Una red que abarca el área de una ciudad (y por lo tanto, cuyos enlaces utilizan espacios
públicos) suele llamarse red metropolitana o MAN (Metropolitan Area Network).
Una red mayor, que cubre distancias entre ciudades, paı́ses o continentes, se llama una
red de área extensa o WAN (Wide Area Network). Las redes de los proveedores
de servicios de Internet (ISPs) suelen clasificarse como WANs.
2. Enlaces.
3. Nodos intermedios.
4. Interfaces.
10.2.1. Hosts
85
86 CAPÍTULO 10. REDES DE COMPUTADORAS
10.2.2. Enlaces
Los enlaces que conectan las computadoras. Los enlaces suelen llamarse punto a punto
cuando conectan únicamente dos nodos, o compartidos cuando al mismo enlace se conectan más
de dos nodos.
Las señales (que representan los bits) son transmitidas sobre un enlace. El material de dicho
enlaces se llama medio del enlace. Las tecnologı́as de construcción de los enlaces son muchas.
Cuando las señales se codifican mediante impulsos eléctricos, como en las redes de cables
de par trenzado o coaxial, el medio es un conductor, como el cobre.
Para distancias mayores (como las transoceánicas) o para ambientes donde existe mucho
ruido o interferencia electromagnética (como en fábricas), se utiliza fibra óptica.
Cuando no es posible o práctico tender un cable, no queda más solución que utilizar
emisiones de radio. Ejemplos de tecnologı́as de radio son los enlaces satelitales, los de
microondas, y las LAN inalámbricas bajo norma 802.11 conocidas popularmente como
WiFi. Estas tecnologı́as utilizan como medio el espacio.
Las principales compañı́as de conectividad del mundo tienden enlaces de fibra óptica trans-
oceánicos. Como la instalación de estos cables es una maniobra muy compleja y tiene un costo
altı́simo, se aseguran de instalar capacidad de transmisión en abundancia. Por ejemplo, uno de
estos enlaces tiene una capacidad de 3.2 Tbps, lo que permitirı́a transmitir el contenido completo
de un disco rı́gido de 1 TB en menos de tres segundos. Esta capacidad es compartida entre varios
proveedores de Internet que compran el servicio de transporte.
Interesante
Submarine Cable Map
En el pasado también se usaron los enlaces satelitales para resolver el problema de cubrir
grandes distancias. Los satélites son repetidores de radio colocados en órbita. Reciben emisiones
de una estación terrena y la comunican a otra distante, superando el problema de la curvatura
terrestre, que no permitirı́a la propagación en lı́nea recta de la emisión de radio.
Su principal inconveniente es la alta latencia o retardo en la llegada de la señal desde un
punto a otro, debido a las grandes distancias que se deben enlazar. Los satélites geoestaciona-
rios o de órbita alta (GEO) se instalan a una altura de alrededor de 35700 km. Al ubicarlos a
esta altura se alcanza un equilibrio entre la fuerza de gravedad terrestre y la fuerza centrı́fuga del
satélite, lo que garantiza que permanecerán inmóviles respecto de algún punto de la superficie
terrestre, y ası́ cubrirán siempre la misma región del planeta. Pero la órbita alta implica una
88 CAPÍTULO 10. REDES DE COMPUTADORAS
gran distancia a recorrer para las señales, lo que introduce demoras de alrededor de un cuarto
de segundo entre estaciones terrestres. Estas demoras son tolerables para algunas aplicaciones
de tráfico de datos, pero perjudiciales para las comunicaciones interactivas.
Paulatinamente van siendo aban-
donados en favor de la fibra óptica
para comunicación de datos a gran-
des distancias. Hoy se estima que
sólo un 5 % del tráfico internacional
es satelital, y el resto es conducido
por fibras ópticas. Sin embargo, si-
guen siendo una buena solución para
atravesar áreas continentales, o para
Figura 10.5: Ejemplo de medio no guiado: Enlace distribuir tráfico hacia muchos pun-
satelital. tos simultáneos de bajada, como en
los medios de comunicación televisi-
vos (aplicación llamada broadcasting).
Los nodos intermedios sirven para compartir un enlace (switches) o encaminar el tráfico
de información entre los nodos terminales (routers).
Switches
En las redes de área local, o LAN, encontramos enlaces compartidos. El cableado de una
oficina, un aula o un edificio es un único medio de comunicación compartido por todos los
nodos de la red. El cableado se concentra en un punto de conmutación llamado switch o,
justamente, conmutador, que distribuye el tráfico entre los nodos conectados. Un switch tiene
muchas interfaces donde se conectan cables punto a punto hacia los nodos de la LAN.
Routers
Suele definirse a Internet como red de redes. Las grandes redes, y en particular Internet, se
componen interconectando redes a través de enlaces, a veces de gran longitud. Entre cada dos
de estas redes siempre existe un router.
10.2. COMPONENTES DE HARDWARE 89
El router presta el servicio que no alcanza a prestar el nivel de enlace, que es el de enviar el
tráfico fuera de la red de origen. El nivel al que pertenecen los routers se llama nivel de red.
Los routers son los elementos que toman
las decisiones de enrutamiento o ruteo, al
determinar por cuál de sus interfaces, que a
veces son muchas, debe ser enviada la infor-
mación que reciben. Esta tarea de enrutar la
información se cumple mediante software de
enrutamiento.
El hardware y el sistema operativo de los
routers pueden estar altamente especializados
en la tarea de ruteo, pero también es perfec-
tamente posible construir un router a partir
de una computadora corriente de escritorio y
Figura 10.7: Router de alto rendimiento. un sistema operativo multipropósito. Es decir
que los routers son computadoras, con un sis-
tema operativo y un hardware similares a los que encontramos en muchas otras computadoras,
pero dedicadas a la tarea del enrutamiento.
Dependiendo del ambiente donde deben
trabajar y de la cantidad de tráfico que deben
procesar, los routers pueden adoptar muchas
formas fı́sicas y tamaños.
10.2.4. Interfaces
Para utilizar la red, todos los nodos que están conectados a ella, ya sean terminales o inter-
medios, corren software de red como protocolos y aplicaciones de red. Los protocolos son,
por un lado, convenciones que establecen con todo detalle cómo se realiza una comunicación, y
por otro lado, los componentes de software que implementan esa forma de comunicación.
Las aplicaciones de red son aplicaciones distribuidas, es decir, se componen de al menos dos
partes, preparadas para comunicarse una con otra, y esas partes funcionan en nodos terminales
de la red diferentes. Cada aplicación de red utiliza un protocolo, porque la interacción entre
10.3. COMPONENTES DE SOFTWARE 91
Figura 10.10: Ejemplo de una aplicación de red (usando protocolo de aplicación ftp).
las partes debe estar perfectamente determinada para que los nodos se entiendan sin errores ni
ambigüedades. Un protocolo puede ser utilizado por varias aplicaciones.
10.3.2. Protocolos
Los protocolos son conjuntos de reglas que definen la interacción entre dos entidades de
la red. Para comunicarse, las entidades de cualquier nivel deben compartir un protocolo. Los
protocolos especifican:
Puede ser útil comparar los protocolos de red con protocolos sencillos de la vida cotidiana.
Muchas interacciones entre las personas están gobernadas por protocolos, a veces poco evidentes.
Por ejemplo, comprar un artı́culo cualquiera en un comercio sigue unas pautas bastante definidas.
Aunque los contenidos especı́ficos de los mensajes pueden variar, es habitual que existan
fases en la interacción entre las personas, como el inicio de sesión, la autentificación, la
autorización, las peticiones o requerimientos (requests), las respuestas (responses),
y el cierre de sesión. Todas éstas son fases habituales en la comunicación entre los humanos,
pero también en los protocolos de las redes.
Las redes pueden estudiarse y comprenderse mediante modelos jerárquicos compuestos por
capas, donde cada pieza de hardware o de software pertenece a una capa o nivel. Cada capa
corresponde a un conjunto de problemas relacionados, y a las soluciones posibles. Para funcionar,
cada capa se apoya en las soluciones provistas por la capa inmediatamente inferior.
Aplicación: En la capa de Aplicación se encuentran los protocolos sobre los cuales se basan
directamente las aplicaciones distribuidas.
Red: La capa de Red soluciona el problema de la entrega de datos entre nodos de diferentes
redes.
Fı́sica: La capa Fı́sica define la forma como se codifican y transmiten las señales que
representan la información.
Para poder dirigir los mensajes entre nodos, es necesario identificarlos de alguna forma,
asignándoles direcciones o identificadores de red. En Internet, las direcciones son asignadas a
las interfaces, y no a los nodos. De esta manera, si un nodo tiene más de una interfaz, recibirá
más de una dirección. El caso tı́pico de un nodo con más de una interfaz son los routers, que
tienen una interfaz perteneciente a cada una de las redes que conectan.
El protocolo IPv4 define las direcciones de red como números de 32 bits que se asignan a
cada interfaz de los nodos. Estas direcciones de 32 bits suelen escribirse como cuatro valores
decimales, entre 0 y 255, separados por puntos.
Ejemplo
10.4.2. Paquetes IP
Internet es una red del tipo de conmutación por paquetes, lo que significa que los flujos de
datos que van de un nodo emisor a un receptor son fraccionados en paquetes o trozos de datos,
de un cierto tamaño máximo, y que los nodos intermedios tratan a cada paquete individualmente
para encaminarlos a su destino.
En una red conmutada por paquetes, los nodos intermedios, o routers, no necesitan conocer
todo el camino que debe atravesar cada uno de los paquetes. En cambio, un router sólo necesita
saber a cuál de los nodos intermedios adyacentes encaminarlo, basándose en información
transportada por el mismo paquete.
Cada nodo intermedio o router en el camino entre el emisor y el receptor tomará una nueva
decisión de ruteo ante cada uno de los paquetes que llegan a él.
10.5. SERVICIO DE NOMBRES DE DOMINIO (DNS) 93
Al generar un paquete, para que pueda ser encaminado, el emisor completa los datos con un
encabezado conteniendo la dirección IP del nodo emisor, o dirección origen, y la dirección
IP del nodo destino, o dirección destino.
Cuando un paquete llega a un router, lo hace por algún enlace. La tarea del router es
reenviar este paquete por otro de sus enlaces, de modo que se aproxime a su destino.
El router debe aplicar alguna regla lógica para decidir hacia qué otro enlace reenviar el
paquete. Esta decisión de cuál será ese otro enlace es una acción de ruteo o encaminamiento.
La decisión de ruteo es tomada por los routers usando la información de destino que llevan
consigo los paquetes, más información de ruteo contenida en una tabla de reenvı́o o tabla de
ruteo, almacenada en la memoria del router. La tabla de ruteo contiene reglas para la decisión
de encaminamiento de los paquetes. Cada regla se llama una ruta e indica cuál será la interfaz
de salida de los paquetes cuya dirección destino coincida con la dirección destino de la ruta. En
lı́neas generales, el algoritmo de ruteo es como sigue (una versión muy simplificada):
Estos nombres simbólicos tienen una cierta estructura jerárquica, es decir, organizada por
niveles. Un nombre consta de varias partes, separadas por puntos. En cada nombre, las partes
más a la derecha designan conjuntos mayores de nodos, y las partes más a la izquierda, conjuntos
más pequeños, contenidos en aquellos conjuntos mayores.
Ejemplo
94 CAPÍTULO 10. REDES DE COMPUTADORAS
Estos conjuntos de nombres se llaman dominios. Los dominios que aparecen más a la derecha
son los más generales. Inicialmente fueron siete de propósito general (org, mil, gov, edu,
com, net, int), más los pertenecientes a los paı́ses (ar para Argentina, cl para Chile, uy
para Uruguay. . . ), pero luego se agregaron otros. Por ser los más generales, están al tope de la
jerarquı́a, y se llaman dominios de nivel superior o TLD (Top-Level Domains).
Los dominios de nivel superior contienen otros espacios de nombres, llamados a su vez do-
minios, y éstos, otros llamados subdominios. En el ejemplo anterior, el TLD es ar, el dominio es
edu.ar (educación, Argentina), el subdominio es uncoma.edu.ar (Universidad del Comahue,
educación, Argentina) y finalmente pedco.uncoma.edu.ar es el nombre de un nodo pertene-
ciente a la Universidad del Comahue, educación, Argentina.
Los servidores DNS se clasifican por el tipo de función que cumplen. Cada uno interviene de
una manera especial en el mecanismo de traducción de nombres a direcciones. Este mecanismo
de traducción se llama resolución de nombres.
Cada nodo de Internet lleva una configuración que le dice cuál es la dirección de su ser-
vidor DNS local. El servidor local es quien responde efectivamente una consulta DNS.
Normalmente, el servidor local se encuentra “cerca” del cliente en términos de redes. Po-
siblemente, en la misma red local, o en la del proveedor de acceso a Internet.
Al ser consultado por un nombre, un servidor local usará la estrategia de analizar ese
nombre de derecha a izquierda. Utilizará los componentes del nombre en ese orden, es
decir, yendo de lo general a lo particular. En primer lugar utilizará el TLD o nombre de
nivel superior para averiguar información sobre ese conjunto de nombres.
Los servidores locales no conocen todas las posibles traducciones de nombre a dirección
IP, por lo cual necesitan el servicio de los servidores raı́z. Estos son alrededor de una
veintena de servidores distribuidos en diferentes lugares del planeta, y todos tienen la
misma información, replicada: las direcciones de los servidores de los TLD.
Ası́, un servidor local obtendrá, de un servidor raı́z, el dato de dónde ubicar al servidor
del TLD ar.
Conociendo la dirección IP del servidor del TLD, el servidor local lo interrogará entonces
acerca del siguiente componente del nombre.
Los servidores de los TLD tampoco conocen todas las posibles traducciones, sino que
conocen las direcciones de los servidores DNS de los dominios por debajo de ellos. Ası́, el
servidor del TLD ar puede decirle al servidor local dónde ubicar al servidor del dominio
edu.ar.
Otra información que este servidor del dominio TLD ar podrı́a darle al servidor local, si
la pidiera, serı́an las direcciones de los servidores de los dominios com.ar, org.ar, etc.
Ahora el servidor local puede consultar al servidor del dominio edu.ar, que es quien puede
informarle la dirección del servidor del subdominio uncoma.edu.ar.
10.6. ADMINISTRACIÓN DE REDES 95
Todo este complejo mecanismo deberı́a tener lugar cada vez que un cliente de la red consulta
por un nombre. Sin embargo, como este mecanismo es costoso en tiempo y en ancho de banda
de las redes, se adopta un esquema de cache o reserva de información. Como es muy probable
que esa información vuelva a ser solicitada, los pares (nombre, dirección) que han sido resueltos
quedan guardados en una memoria temporaria o cache del servidor local. De esta manera las
próximas consultas podrán responderse sin necesidad de volver a generar tráfico hacia el resto
de la Internet.
El comando ping emite paquetes hacia un nodo destino. Si los paquetes logran atravesar
la Internet, el nodo destino emitirá una respuesta. El comando ping muestra los paquetes de
respuesta que llegan o se pierden, y el tiempo que demora cada respuesta en llegar.
Cuando los usuarios tienen problemas con alguna aplicación de red, el comando ping es útil
como herramienta de diagnóstico porque permite saber si la red es capaz de hacer llegar paquetes
de un nodo a otro. Si el diagnóstico de ping es positivo, el administrador de red no se preocupa
en comprobar cuestiones asociadas con los niveles inferiores a la capa de red: la comunicación
a nivel fı́sico, de enlace y de red entre ambos nodos es operativa. Si existe alguna condición de
error, se deberá a problemas relacionados con las aplicaciones, que habrá que investigar.
El comando traceroute permite investigar cuál es la cadena particular de routers que debe
atravesar un paquete para llegar a un destino dado. Además, da información sobre la demora
96 CAPÍTULO 10. REDES DE COMPUTADORAS
en atravesar cada enlace, lo que puede dar una idea de si existe una condición de congestión
en el camino de los paquetes, y en qué lugar de Internet.
Una condición de congestión es aquella que aparece cuando los nodos intentan utilizar un
enlace más allá de su capacidad. Si un enlace es capaz de transmitir una cantidad de bits por
segundo, y las demandas de los nodos de la red superan esa capacidad, el router comienza a
acumular o encolar paquetes hasta que no tiene más espacio en su memoria para almacenarlos.
A partir de este momento, si llegan nuevos paquetes, simplemente los descarta. El programa
traceroute hace evidentes las pérdidas de paquetes, y dice en cuál de los enlaces ocurren.
El programa traceroute también permite detectar anomalı́as de ruteo como los lazos o ciclos
de ruteo, que se producen cuando los paquetes toman caminos circulares de los cuales no pueden
salir.