Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Introducción
El NF1 “Introducción a los sistemas operativos” nos servirá para dos fines. Primero
realizaremos una breve presentación de la noción del concepto de “Informática” y
veremos que es un concepto muy amplio y que comprende muchos elementos
distintos. Segundo definiremos la noción de “Sistemas Informáticos”, que es la que da
nombre a nuestra asignatura.
1
1.2 El ordenador. Fundamentos estructurales y de funcionamiento
A partir de la definición de Informática como “información automática”, nuestro primer
objeto de interés va a ser conocer cómo la información es almacenada en un sistema
informático. Para ello explicaremos la diferencia entre señales analógicas y señales
digitales. Posteriormente, presentaremos la estructura básica de un ordenador, con el
fin de saber cómo la información almacenada en un dispositivo puede ser procesada.
2
En la imagen siguiente podemos observar una memoria de una computadora (del año
1980) en la cual el tamaño de los bits se puede comprobar a simple vista. La memoria
contiene 4096 celdas o bits, y su tamaño es aproximadamente 4 * 4 cm.
3
00000000 00100000 01000000 01100000 10000000 10100000 11000000 11100000
00000001 00100001 01000001 01100001 10000001 10100001 11000001 11100001
00000010 00100010 01000010 01100010 10000010 10100010 11000010 11100010
00000011 00100011 01000011 01100011 10000011 10100011 11000011 11100011
00000100 00100100 01000100 01100100 10000100 10100100 11000100 11100100
00000101 00100101 01000101 01100101 10000101 10100101 11000101 11100101
00000110 00100110 01000110 01100110 10000110 10100110 11000110 11100110
00000111 00100111 01000111 01100111 10000111 10100111 11000111 11100111
00001000 00101000 01001000 01101000 10001000 10101000 11001000 11101000
00001001 00101001 01001001 01101001 10001001 10101001 11001001 11101001
00001010 00101010 01001010 01101010 10001010 10101010 11001010 11101010
00001011 00101011 01001011 01101011 10001011 10101011 11001011 11101011
00001100 00101100 01001100 01101100 10001100 10101100 11001100 11101100
00001101 00101101 01001101 01101101 10001101 10101101 11001101 11101101
00001110 00101110 01001110 01101110 10001110 10101110 11001110 11101110
00001111 00101111 01001111 01101111 10001111 10101111 11001111 11101111
00010000 00110000 01010000 01110000 10010000 10110000 11010000 11110000
00010001 00110001 01010001 01110001 10010001 10110001 11010001 11110001
00010010 00110010 01010010 01110010 10010010 10110010 11010010 11110010
00010011 00110011 01010011 01110011 10010011 10110011 11010011 11110011
00010100 00110100 01010100 01110100 10010100 10110100 11010100 11110100
00010101 00110101 01010101 01110101 10010101 10110101 11010101 11110101
00010110 00110110 01010110 01110110 10010110 10110110 11010110 11110110
00010111 00110111 01010111 01110111 10010111 10110111 11010111 11110111
00011000 00111000 01011000 01111000 10011000 10111000 11011000 11111000
00011001 00111001 01011001 01111001 10011001 10111001 11011001 11111001
00011010 00111010 01011010 01111010 10011010 10111010 11011010 11111010
00011011 00111011 01011011 01111011 10011011 10111011 11011011 11111011
00011100 00111100 01011100 01111100 10011100 10111100 11011100 11111100
00011101 00111101 01011101 01111101 10011101 10111101 11011101 11111101
00011110 00111110 01011110 01111110 10011110 10111110 11011110 11111110
00011111 00111111 01011111 01111111 10011111 10111111 11011111 11111111
4
Lo que un conjunto de ceros y unos signifique depende de la manera en que nosotros
hayamos decidido codificar nuestra información (por ejemplo, de la codificación de
caracteres que utilice nuestro sistema, o de la tabla de caracteres vigente), pero es
importante tener presente que la información guardada en un sistema digital (en una
memoria) siempre lo estará, en última instancia, en formato binario.
5
caracteres para Asia que un repertorio de caracteres centroeuropeos o de
Europa Occidental). En un sencillo ejemplo, podríamos considerar como un
repertorio de caracteres el conjunto {a, e, i, o, u, A, E, I, O, U, á, é, í, ó, ú}.
Tabla de caracteres: una tabla de caracteres puede entenderse como una
aplicación que a cada carácter (de un repertorio de caracteres) le asigna un
número entero (no negativo). El número entero suele ser conocido como
“código de posición” (en la tabla de caracteres) o “número de código”. El
anterior repertorio de caracteres podría ser representado ahora por la siguiente
tabla de caracteres: {a=1, e=2, i=3, o=4, u=5, A=6, E=7, I=8, O=9, U=10, á=11,
é=12, í=13, ó=14, ú=15}, pero también por otras tablas de caracteres distintas
(por ejemplo, en orden inverso, o sólo por números pares).
Codificación de caracteres: una codificación de caracteres es un algoritmo o
regla que permite convertir los códigos de posición de una tabla de caracteres
en octetos (o secuencias de octetos). La codificación más sencilla es convertir
cada código a su representación binaria {a = 00000001, b = 00000010, c =
00000011…}. Esto funciona bien para tablas de menos de 256 caracteres. Sin
embargo, es muy fácil encontrar otras codificaciones diferentes; por ejemplo,
invirtiendo el orden de los bits: {a = 10000000, b = 01000000, c = 11000000…}.
Para tablas con más de 256 elementos los algoritmos son más complejos, ya
que se hace necesario más de un octeto.
Los ordenadores de los años 80 utilizaban procesadores de 8 bits (un octeto), y eso
hizo que la mayor parte de las codificaciones de caracteres se ajustaran a esas
dimensiones (es decir, que cada palabra ocupe un octeto). Es importante notar que
toda codificación que ocupe un octeto va a permitir representar un máximo de 256
caracteres (28=256).
¿Pero quién decide que código corresponde a cada carácter? Y es con esta pregunta
con la que empieza el caos de los sistemas de codificación. La informática tuvo sus
orígenes en el mundo anglosajón, y por consiguiente los caracteres ingleses fueron los
prioritarios a la hora de asignar estos valores binarios a los distintos caracteres. Y así
nació ASCII. El estándar ASCII (American Standard Code for Information
Interexchange) es una de las tablas o normas de codificación que se hicieron más
populares. Siendo un estándar de origen occidental (más concretamente
norteamericano) sirve para codificar caracteres latinos (por supuesto, no contiene
caracteres cirílicos, hebreos, árabes, chinos,…).
Sus principales características serían las siguientes. Su repertorio de caracteres está
compuesto sólo por 128 caracteres y símbolos de control. De éstos, 32 corresponden
a caracteres de control, algunos de los cuales se usaban en aquella época para enviar
señales a dispositivos periféricos, tales como impresoras, y el resto se corresponden
con caracteres estándar (mayúsculas, minúsculas, signos de puntuación…). Se puede
encontrar la definición concreta de los operadores de control en el sitio:
http://es.wikipedia.org/wiki/ASCII.
La tabla de caracteres ASCII con sus códigos de posición sería la siguiente:
6
El repertorio de caracteres ASCII consta sólo de 128 caracteres. Si observamos que
27=128, con 7 bits sería suficiente para poder codificar la tabla de caracteres ASCII.
Sin embargo, internamente, y ya que la longitud de palabra del ordenador es el octeto,
cada carácter se codifica con 8 bits. Para ello el proceso (o algoritmo) de codificación
sería el siguiente. A cada carácter se le asignan los 7 bits correspondientes a la
codificación en binario de su posición en la tabla de caracteres. Por ejemplo, al
carácter “O”, cuya posición en la tabla es 79 (puedes contar las columnas, o convertir
4 – 15 de hexadecimal a digital para conocerlo), le asignamos los 7 bits de su
representación binaria (79 = 1*26 + 0*25 + 0*24 + 1*23 + 1*22 + 1*21 1*20), es decir,
1001111. A estos 7 bits se le añade el llamado “bit de paridad”, que colocaremos en
primera posición. Para calcularlo, contamos el número de “1”s en la representación
binaria (en este caso 5), y la convertimos en par (de ahí el nombre de bit de paridad),
añadiendo un nuevo 1. Finalmente, la codificación del carácter “O” queda como
“11001111”. Si el carácter a representar fuese la letra “P”, cuya posición en la tabla es
80 = 0*20 + 0*21 + 0*22 + 0*23 + 1*24 + 0*25 + 1*26 su bit de paridad será 0 (ya que la
codificación anterior contiene dos “1” y ya es par), y por tanto, quedaría como
01010000.
El repertorio (y la tabla) de caracteres ASCII se convirtió en un estándar de facto, pero
pronto se vieron sus limitaciones, sobre todo por el corto número de caracteres que se
pueden codificar en la misma (se puede observar, por ejemplo, que no se pueden
encontrar ni vocales acentuadas “á, é, í…”, ni la letra “ñ”, ni la “u” con diéresis “ü”,
propios del castellano, ni la ç, o las vocales à, è, ò del catalán y muchos otros
caracteres de otros idiomas).
Cuando se planteó representar caracteres de otros alfabetos se vio claramente que
ese octavo bit de ASCII (que es un bit destinado al control de errores, y no un bit
informativo) era una oportunidad fantástica para ampliar con 128 nuevos códigos el
juego ya existente. Se definieron nuevos repertorios de caracteres, que utilizaran al
menos toda la capacidad del octeto (256 valores) para codificar más caracteres.
Debido al papel preponderante que había adquirido ASCII en el mercado de los
ordenadores, las tablas de caracteres que surgieron después coincidieron en incluir los
caracteres “representables” ASCII (es decir, desde el 33 al 128) codificados de la
misma forma que en la norma ASCII. De esta forma se asegura que cualquier texto
7
que contenga sólo caracteres de la norma ASCII se pondrán guardar y leer en
cualquier norma de codificación que respete ésta norma.
Por tanto, se aumentó la norma ASCII por la conocida como ASCII extendida.
Existen múltiples códigos ASCII extendidos. Su principal característica es que
mantienen los caracteres del 33 al 128 idénticos a los de ASCII (los caracteres
de control en las posiciones 1 a 32 pueden variar). Los caracteres 129 a 256 se
utilizan para codificar caracteres propios de distintas regiones o lenguas.
Algunas de estas codificaciones son la ISO-8859-1 (también conocida como
ISOLatin1, creada con el propósito de representar los caracteres de la mayor parte de
los alfabetos derivados del latín), cuyos caracteres imprimibles puedes encontrar
en http://es.wikipedia.org/wiki/ISO-8859-1 (coincide en el rango 1 – 128 con la
tabla ASCII), la 850 (DOSLatin1), página de códigos que se utiliza en la consola
de MSDOS para Europa Occidental, cuya codificación se puede encontrar en
http://aspell.net/charsets/codepages.html o Windows-1252 (WinLatin1), que
también se puede encontrar en el sitio
http://aspell.net/charsets/codepages.html. Es interesante comprobar algunos
caracteres especiales (entre las posiciones 129 y 256) en cada una de ellas y
ver si coinciden o no, eso podría explicar algunos fallos de visualización que
podemos encontrar en algunos ficheros de texto o páginas web. La falta de un
estándar globalmente aceptado y la diversificación de normas de codificación
llevaron a la creación del repertorio de caracteres Unicode. Unicode es un
estándar de representación de caracteres que pretende facilitar el trabajo con
caracteres de múltiples idiomas (incluyendo lenguas muertas o lenguas
basadas en ideogramas como chino, coreano, japonés) o disciplinas técnicas
(como matemáticas, física, química, ingeniería). Básicamente es el estándar
encargado de asignarle un código numérico a cada uno de los distintos
caracteres representables sobre la faz de la tierra. Unicode tiene como objetivo
representar un repertorio de caracteres global, y su posición (es decir, la tabla
de caracteres). Otra cosa es la presentación de los algoritmos y reglas de
codificación de dichos caracteres. Los repertorios de la totalidad de las tablas
de representación de caracteres son muy extensos y se pueden encontrar en
http://en.wikibooks.org/wiki/Unicode/Character_reference/0000-0FFF.
Si navegas por esta página podrás observar que hay al menos otras 15 tablas
como la anterior (cada una con 4096 caracteres), dando lugar a lo que se
conoce como BMP (Basic Multilingual Plane), y algunas otras más. La tabla
anterior sólo contiene 163 = 4096 caracteres (a día de hoy se calcula que
Unicode cuenta con más de 100.000 símbolos ya definidos, y dispone de
espacio para al menos 220 símbolos).
8
ejemplo, el carácter e se representa mediante la secuencia U+0065. Pero
todavía no hemos dicho nada de la codificación de estos caracteres en sistema
binario. Se puede observar que el carácter e usa el mismo código numérico en
ASCII y en Unicode. Y es que ésta es una de las grandes cualidades de
Unicode, los primeros caracteres son los ASCII, por lo que en sus primeros
valores al menos, es compatible con el estándar de facto anterior.
9
sólo un octeto (un byte) en codificación UTF-8. Sería interesante comparar los
símbolos que ocupan en la tabla Unicode las posiciones del 129 al 256 con los
equivalentes de ISO-8859-1 o Windows-1252.
- Las filas siguientes, de la “0100” en adelante, contienen los símbolos Unicode a
partir del 256. Si los observas verás que algunos de ellos son de uso muy
extendido. Su codificación requiere más de un octeto. Sin embargo UTF-8 permite
codificar los mismos gracias a su longitud variable.
UTF-8
U-00000000 - U-0000007F:0xxxxxxx
U-00000080 - U-000007FF:110xxxxx 10xxxxxx
U-00000800 - U-0000FFFF:1110xxxx 10xxxxxx 10xxxxxx
U-00010000 - U-001FFFFF:11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
U-00200000 - U-03FFFFFF:111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
U-04000000 - U-7FFFFFFF:1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
10
El algoritmo de codificación que utiliza UFT-8 funciona de la siguiente manera.
En base al código numérico Unicode, el carácter ocupará uno o más bytes.
Para saber el número de bytes que ocupará la propia codificación contiene ésta
información. Esto que parece muy complicado es muy sencillo verlo con la
tabla anterior. La primera columna indica el último código numérico Unicode
que entra en ese grupo, y las siguientes columnas indican cómo se codifica
cada uno de los bytes UTF-8. Los valores numéricos (en verde) son fijos, y
gracias a que lo son, dependiendo de cómo empiece el primer byte se puede
saber cuántos bytes ocupa el carácter. Por otra parte, los valores que tienen
una X (en rojo) se rellenan con el código numérico Unicode del carácter que
queramos codificar.
Este ejemplo era del tercer grupo, que ocupan 3Bytes, pero como podemos ver
en la primera tabla, los caracteres que están entre U+0000 y U+007F se codifican
con un solo byte, en el que el primer bit es un 0. Pero, ¿qué caracteres son
esos? ¡¡Efectivamente!! Son los de la tabla ASCII. Es decir, hemos conseguido
que los caracteres de la tabla ASCII y los codificados en UTF-8 se vean
exactamente igual (sus códigos numéricos son los mismos, y su representación
binaria también). Por tanto, un documento que sólo contenga caracteres de la
11
tabla ASCII es indistinguible si está codificado en ASCII o si lo está en UTF-8:
son exactamente iguales a nivel binario. Pero por ejemplo, la ñ tiene el código
numérico U+00F1. Este código está en el segundo conjunto de los mostrados
anteriormente, por lo que ocupará 2B. Y ya deja de ser compatible con la
codificación ISO-8859-1 (extensión de ASCII para Europa occidental), por lo
que si abrimos con UTF-8 un documento en castellano que fue codificado con
ISO-8859-1, se nos mostrarán caracteres extraños.
Y si nos vamos a caracteres más altos en la tabla Unicode podemos ver como
empiezan a ocupar bastante más, hasta poder llegar a los 6Bytes. Pero aun
así, esta codificación ha demostrado ser la óptima a la hora de ahorrar espacio.
La mayor parte de la información que se codifica actualmente está contenida
en la tabla ASCII o en las siguientes posiciones, por lo que en la mayor parte
de los casos esta codificación siempre ocupará lo mismo, o menos que los
"hermanos" mayores de Unicode (Unicode 16 y Unicode 32).
12
La ordenación de bytes en un archivo. Big Endian, Little Endian
y BOM (Bit Order Mask)
Con el mapa de caracteres Unicode obtenemos el llamado “code point” para un
carácter, es decir el número de orden que le corresponde del total del conjunto
de caracteres. Con el code point y eligiendo un “encoding” (el algoritmo de
codificación del carácter, es decir, UTF-8, UTF-16, UTF-32...) obtenemos la
secuencia de bytes que lo representará. Pero aun así, no lo tenemos todo para
transferir o almacenar Unicode. Existe un problema y es que según sea la
arquitectura de un ordenador los mismos bytes se guardan en un orden en el
inverso. Existen arquitecturas llamada “big endian” y arquitecturas “little
endian”. Tanto UTF-16 y UTF-32 permiten guardar los bytes tanto en formato
“big endian” como “little endian”, pero habrá que definirlo de alguna forma en el
documento. También sería conveniente tener algún mecanismo para saber qué
tipo de encoding está usando un documento. Para resolver estos dos
problemas existe el BOM (Bit Order Mask). Consiste, simplemente, en añadir
una firma al principio del documento que le indica al sistema (sea Word, vim o
nuestro navegador web preferido) que está leyendo un texto codificado en UTF,
y con qué ordenamiento de bytes se lo va a encontrar.El BOM es una
secuencia de 2 o 4 bytes al inicio de un documento Unicode que indica su
encoding y si se ha utilizado big o little endian.
13
Otras observaciones: caracteres, glifos y grafemas
Si bien ya hemos descrito los principios necesarios para saber leer, transportar y almacenar
Unicode, todavía es necesario saber cómo mostrar los caracteres en pantalla o en algún otro
medio visual. Para eso usaremos una tipografía. Una tipografía asocia una forma a un
determinado carácter. De modo que, por ejemplo, el carácter "a" tendrá
diferentes formas según la tipografía que estemos utilizando. A esta forma se le
denomina glifo.
Pero no todo es tan sencillo. Unicode permite representar algunos caracteres de dos formas.
Por ejemplo "á" puede ser representado como U+00E3 ("letra latina 'a' con acento") o como
una forma compuesta de U+0061 ("letra latina 'a'") y U+0303 ("acento”). Estas formas
compuestas se denominan grafemas. Esto significa que un carácter puede ser representado
por más de un “code point”.
#!/usr/bin/python
También ten en cuenta que algunos formatos de fichero no soportan ser creados en cualquier
codificación. Por ejemplo en Java los archivos de propiedades deben ser escritos en ISO-8859-
1, a no ser que uses el formato XML.
En aplicaciones web...
En la cabecera HTTP Content-Type define la codificación de caracteres además del tipo MIME.
14
Content-Type: text/html;charset=UTF-8
Sino defines el accept-charset es posible que el navegador te envíe los datos en ISO-8859-1
aunque el formulario se encuentre en una página codificada con UTF-8.
En tu base de datos
Asegúrate de que tienes configurada la base de datos para almacenar el texto en UTF-8. No te
servirá de nada que el resto de la aplicación esté configurado para usar UTF-8 si tu base de
datos no lo soporta.
Y ten siempre en cuenta una cosa. En realidad, no existe el "text plain" como comúnmente se
entiende. Todo texto informatizado tiene su codificación de caracteres. Tenlo siempre
presente. Parte de nuestro trabajo será crear y gestionar texto codificado de diferentes formas.
Prueba tu aplicación con caracteres que tengan code points mayores que los definidos en el
estándar ASCII. La compatibilidad entre UTF-8, ASCII y las codificaciones de ASCII
extendido ha provocado que muchas aplicaciones estén mal programadas aunque
"aparentemente" y "normalmente" hagan bien su trabajo. Pero si a estas aplicaciones les pasas
caracteres fuera de la tabla ASCII, dejan de procesar correctamente el texto. ¡Entonces es que
en ningún momento lo procesaban bien! Solo que con el subconjunto compatible no había
habido problemas hasta entonces.
15
Unidades de información
16