Aunque nunca hayamos usado
UNIX, casi todos los sistemas de la actualidad
tienen conceptos tomados de él
incluyendo al DOS, OS/2, NT, etc.
UNIX es algo así como el
latín de los sistemas operativos. Uno de los factores que motivan el que hoy se
escuche más acerca de este sistema operativo es la aparición del LINUX ,un clon
de UNIX freeware.
La palabra UNIX es una marca
registrada ,que fue pasando de manos con el tiempo y actualmente esta en poder
de Novell. Sin embargo ,muchas empresas diseñaron sistemas UNIX compatibles. Cuando se habla de compatibilidad
entre UNIX , generalmente se habla de compatibilidad nivel código fuente.
O sea que se puede tomar un programa escrito en C para una plataforma, compilarlo y usarlo en otra. Los sistemas operativos ”a lo UNIX” son: SCO UNIX,BSD UNIX ,AIX DE IBM, UnixWare de Novell Linux. UNIX es un muy buen SO y se puede usar para casi todo, pero el ámbito en donde se destaca es en redes. Y esto incluye Internet .Como Internet en sus comienzos estuvo lejos del publico en general, y mas cerca de los investigadores, fue natural que la plataforma de elección fuera UNIX.Y es así como todos los conceptos que giran en torno a Internet, sus protocolos, sus servicios, tienen alguna relación con UNIX.
La interfase gráfica que se usa en el ambiente UNIX se llama Xwindows, y es muy poderosa .Esta diseñada para trabajar en cualquier sistema operativo y cualquier computadora ,y para funcionar sobre una red con las aplicaciones corriendo en una maquina remota.
La forma de moverse dentro de UNIX es parecida a DOS .Los comando mas comunes son:
Pwd..........para averiguar
cual es el directorio actual
Is..............para pedir
un listado del directorio actual
cd.............para cambiar
el directorio
mkdir.......para crear un
directorio
cat............para ver un
archivo
echo.........imprime una cadena
de caracteres
cp.............copia un
archivo
mv............mueve o
renombra un archivo
SISTEMAS DE ARCHIVOS
El
sistema de archivos de Unix; esta basado en un modelo arborescente y recursivo,
en el cual los nodos pueden ser tanto archivos como directorios, y estos
últimos pueden contener a su vez directorios o subdirectorios. Debido a esta
filosofía, se maneja al sistema con muy pocas órdenes, que permiten una gran
gama de posibilidades. Todo archivo de Unix está controlado por múltiples
niveles de protección, que especifican los permisos de acceso al mismo. La
diferencia que existe entre un archivo de datos, un programa, un manejador de
entrada/salida o una instrucción ejecutable se refleja en estos parámetros, de
modo que el sistema operativo adquiere características de coherencia y
elegancia que lo distinguen.
La
gestión de archivos viene implementada por mecanismos propios de UNIX. Esta
aproximación tiene consecuencias directas sobre la seguridad del sistema.
UNIX
comporta un sistema de gestión de ficheros ( SGF ) que permite al usuario
guardar sus datos en disco. Par gestionar la información en forma estructurada,
el SGF debe organizar el disco de determinada manera y crear un sistema de
ficheros ( SGF ) en el momento de realizar una operación de formateo lógico (
diferente del formateo físico del disco realizado por su controlado.
El SGF
designa el mecanismo que permite acceder a los objetos de la entidad SF. Un SGF
complejo puede gestionar varios tipos de SF diferentes a la manera de VFS
(Virtual File System ) de SVR4.
Los
sistemas de ficheros se gestionan como dispositivos en modo bloque, se
encuentran en el directorio /dev/dsk (Disk). Los Sf pueden ocupar físicamente
todo o parte de un disco, sus nombres se refieren pues al disco físico.
Según
los sistemas, se encuentran:
·
Bien
c0d2s1 de Controler 0 Drive 2 Slice ( slice=partición)
·
Bien
0s1 de Controler 0 Slice 1.
En el directorio
/dev/rdsk (Raw Disk) se encuentran los mismos nombres. Estos dispositivos
designan los mismos SF del directorio /dev/dsk pero en modo carácter. Se puede
verificar que los menores y los mayores corresponden. Al escribir y leer sobre
estos dispositivos, se accede directamente a la partición, aunque ésta no sea
UNIX y ello ignorado toda estructura propia de un sistema de gestión de
ficheros.
Generalmente
el dispositivo 0s0 (o c0d0s0) se refiere a todo el disco físico
independientemente de su particionamiento. Por razones de seguridad, es pues
muy importante prohibir los derechos de lectura-escritura-ejecución para group
y other ( el propietario debe ser el superusuario )
Un
SF ( sistema de archivos ) esta dividido
en bloques lógicos cuyo tamaño varia según su tipo: 512. 1024 o 2048 octetos.
El
superbloque describe todas las características del Sf. Ocupa el bloque numérico
1, pero ciertos SF hacen una copia en el segundo. Los bloques 0 y 3 no se
utilizan.

![]()
![]()
x
![]()
x
Superbloque
Tabla de inodos
Bloque de datos
Un inodo
describe las características de un objeto del SGF ( fichero normal, conexión con
nombre directorio, dispositivo ) Se encuentra por ejemplo su tipo, su fecha de
creación, y punteros a las tablas que describen los sectores ocupados por el
fichero. En SVR3.2, el tamaño máximo de un fichero es de 16 gigaoctetos.
Un
bloque lógico asignado a la descripción de un directorio tiene la estructura
siguiente:
![]()

2 octetos
100
105
358
205
titi
< inodo > es el número de inodos (
identificador interno de un fichero ) que es en realidad un índice en la tabla
de
inodos.
< Nombre > es el identificador
externo.
Un sistema de ficheros puede crearse tanto en disco duro como disquete si el sistema integra los dispositivos de modo bloque correspondiente.
Un sistema
de ficheros esta vinculado al sistema de ficheros raíz mediante una operación
de montaje. El punto de montaje esta constituido por un directorio vacío al que
se engancha un volumen lógico gestionado por SGF. Cuando el usuario se refiere
a este directorio ( o a un archivo de este directorio ), UNIX hace referencia
al dispositivo en modo bloque asociado tal como se describe en la VTOC.
UNIX
gestiona los acceso a los ficheros ( directorio, dispositivo, ficheros normales
) por medio del triplete lectura-escritura-ejecución que se repite en tres
ocasiones, una primera para el propietario, la segunda para el grupo y la
tercera para los demás.
Para los
ficheros ( normales, dispositivos, conexiones con nombre ) los derechos de
acceso son :
r lectura
w escritura
x ejecución
La verdadera seguridad en UNIX se encuentra a nivel de directorios. Así, los derechos de acceso significan:
r lee el contenido del directorio, es decir él numero
de inodo y su nombre. Por ejemplo, el usuario no puede ejecutar en el mandatos
ls –l, sino solamente ls.
w escribe en el directorio, es decir crea y suprime
objetos ( ficheros, directorios)
x proporciona el derecho a recorrer el directorio ( recorrer
los subdirectorios ) y utilizar informaciones de los objetos del directorio, es
decir, acceder a los inodos.
El ejemplo siguiente ilustra la importancia de los derechos de acceso sobre los directorios.


/toto


user1
user2


![]()

![]()





f11 f12
f13 f21 f22 f23
Con los
derechos de acceso posicionados como en el ejemplo anterior, los archivos accesibles a user1 para lectura son :
·
f11, f12, f13.
No tiene acceso a ninguno de los archivos de user2 porque no tiene derecho en ejecución sobre el directorio /toto/user2 para group.
Los
archivos accesibles en modo lectura para user2 son:
·
f21, f22, f23.
·
f11 y f13 ( el archivo f12
requiere el derecho de lectura para el grupo )
Los
archivos que puede suprimir user2 son:
·
f21, f22, f23.
·
f11, f12, f13 ( el directorio /toto/user1
tiene el derecho en ejecución para el grupo )
Par
ejecutar un programa en un directorio, solamente es necesario el derecho en
ejecución sobre este ultimo. Si el derecho en lectura no esta autorizado para
este directorio, el usuario no podrá ejecutar todo programa que se encuentre en
el ( con los derechos de lectura-ejecución )
Todo en el sistema UNIX son
archivos. El sistema de archivos es indispensable para el éxito y utilidad del
sistema UNIX.
Conceptos básicos sobre archivos.
Un archivo es una secuencia
de bytes. (Un byte es un pequeño trozo de información, normalmente compuesto
por 8 bits. Para nuestro propósito, un byte es equivalente a un carácter.) El
sistema no impone estructura alguna a los archivos, ni asigna significado a su
contenido ; el significado de los byte depende únicamente de los programas
que interpretan el archivo. Además, esto es cierto no solo para archivos en disco
sino también para dispositivos periféricos. Cintas magnéticas, mensajes de
correo, caracteres de teclados, salidas de impresoras, datos que fluyen en
interconexiones, cada uno de estos archivos no es mas que un secuencia de bytes
desde el punto de vista del sistema y sus programas.
Cada byte de un archivo
contiene un numero de tamaño suficiente para representar un carácter. El código
empleado en la mayoría de los sistemas UNIX es ASCII (“Código Norteamericano
Estándar para Intercambio de Información”), Pero algunas computadoras, entre
las que sobresalen las IBM, usan un código llamado EBCDIC (“Código Extendido de
Intercambio Decimal Codificado en Binario”).
Los programas obtienen los
datos de un archivo por medio de una llamada al sistema (una rutina del núcleo)
llamada read . Cada vez que se invoca
a read , esta regresa la siguiente porción de un archivo, la
siguiente línea de texto tecleada en la terminal , por ej. read también indica cuantos
bytes trae el archivo, por lo que al final del archivo es identificado en el
momento en que read dice “ se traen cero bytes”. Si se hubieran
quedado algunos bytes en el archivó, read
los hubiera leído. En realidad ,
tiene sentido no representar el final de un archivo con algún valor en
especial, ya que, como se menciono anteriormente , el significado de los bytes
depende de como se vaya a interpretar el archivo. Pero todos los archivos tienen un final, y como todos los archivos
deben accesarse por medio de read , regresar un cero es una manera
de representar el final de un archivo ( independientemente de cualquier
representación ) sin introducir ningún carácter especial.
Cuando un programa lee de la
terminal el núcleo envía al programa cada una de las líneas de entrada solo
cuando se teclea su carácter de nueva-linea (es decir, cuando se oprime RETURN
). Por lo tanto si se comete un error mecanografico, uno puede corregirlo si es
que se lo detecta antes de teclear el carácter de nueva-linea. Si no es así la
línea ya ha sido leída por el sistema y
no podrá corregirse.
¿ Que hay en un
archivo ?
El formato de un archivo
depende de los programas que lo usen ; existe gran variedad de estos de
archivos, debido a que también existen muchos programas. Sin embargo, puesto
que los tipos de archivos no son determinados por el sistema de archivos, el
núcleo no puede decirnos cual es el tipo de un archivo : no lo conoce.
$ file /bin /bin/de /usr/ src/ cmd/ de.c/ usr/ man/ man1/ de.1
/bin : directory
/bin/
de : pure executable
/usr/ src/ cmd/
de.c : c program text
/usr/ man /,an.1/
de.1 : roff, nroff, or eqn
input text
Estos son cuatro archivos
típicos, relacionados todos con el editor : el directorio en el cual este
se encuentra (/ bin), el programa
mismo en su forma ejecutable o binaria (/
bin/ ed) , el o conjunto de instrucciones en C que definen el programa (/ usr/ src/ cmd/ de.c) y el manual (/
usr/ man/ man1/ de.1).
Para determinar los tipos,
File no puso atención a los nombres (aunque podría hacerlo), ya que las
convenciones con los nombres, por el echo mismo de no ser mas que convenciones,
no son confiables. Por ejemplo, los archivos con subfijo .c
son programas fuentes en C, pero nada impide al usuario crear un archivo
.c con un contenido arbitrario. En vez de eso, el comando file lee unos cuantos
cientos de bytes al principio del archivo y busca indicios que indiquen el tipo
de archivo en cuestión.
Algunas veces los indicios para
identificar un archivos son obvios. Un programa ejecutable se marca con un
“numero mágico” binario al principio. El comando od sin ninguna opción vacía el
archivo en palabras de 16 bits (o dos bytes) y hacen visible el numero
mágico :
$ od /bin /de
0000000 000410 025000 000462 011444 000000 000000 000000 000001
0000020 170011 016600 000002 005060 177776 010600 162706 000004
0000040 016616 000004 005720 010066 000002 005720 001376 020076
El valor octal 410 “marca”
un programa ejecutable puro, un programa cuyo código puede ser compartido por
varios procesos. (los números mágicos específicos son dependientes del
sistema). El patrón de bits representado por 410 no es un texto en ASCII, por
lo que este valor no podría ser
generado inadvertidamente por un programa tal como un editor. Sin embargo, el
lector puede crear un archivo así ejecutando un programa propio, y el sistema
entenderá la convención de que tales archivo son programas en binario.
Para archivos de texto, los indicios que indicar el tipo de archivo en cuestión pueden encontrarse mas escondidos en el. Por ejemplo, el comando file buscará palabras como #include para identificar programas fuente en C, o líneas que comiencen con un punto para identificar entradas para nroffo o troff.
Cada
archivo tiene un conjunto de permisos asociados con él, los cuales determinen
que hacerse con el archivo y quien puede hacerlo.
Existe
un usuario especial en cada sistema UNIX, llamado superusuario, quien puede
leer o modificar cualquier archivo en el sistema. La clase de acceso especial
root posee privilegios de superusuario: esta la emplean los administradores del
sistema cuando llevan a cabo el mantenimiento del mismo. Existe también un
comando llamado su que otorga un status de superusuario si se conoce la
contraseña de root. Por eso no es recomendable guarda ningún material
confidencial en el sistema de archivos.
Si el
usuario requiere mayor seguridad, puede cambiar los datos en un archivo de
manera que ni aun el superusuario puede leerla ( o al menos entenderla ) usando
el comando crypt.
Cuando
un usuario entra en sesión, teclea un nombre y después confirma que
efectivamente es esa persona tecleando una contraseña ( password ) El nombre es
la identificación para iniciar la sesión del usuario, o login-id. Pero el
sistema en realidad reconoce al usuario por medio de un número, llamado su “
identificación ( o identificación ) de usuario ” o uid.
El
sistema de archivos y por tanto el sistema UNIX en general determinan lo que el
usuario hacer mediante los permisos otorgados a su uid y a su group-id.
El archivo es texto
ordinario, pero las definiciones de los campos y los separadores son una
convención reconocida por los programas que usan la información del archivo.
Existen tres
tipos de permisos para cada archivo: leer
( es decir, examinar su contenido ), escribir ( es decir, cambiar su
contenido ) y ejecución ( es decir, ejecutarlo como un programa ). Además, se
puede aplicar un permiso diferente a cada persona. Como dueño de un archivo, el
lector posee un conjunto de permisos de lectura, escritura y ejecución. Su
grupo tiene otro conjunto. Los demás tienen un tercer conjunto.
El bit
de set-uid es una idea simple pero elegante que resuelve varios problemas de
seguridad.
Es particularmente
serio para un programa con atributo set-uid ya que root tiene permisos de
acceso a cualquier archivo en el sistema. ( Algunos sistemas UNIX apagan el
bit-uid cuando un archivo se modifica, para reducir el peligro de una falla de
seguridad )
Existen llamadas al sistema
que crean y borran archivos, y solo a través de ellas es posible cambiar el
contenido de un directorio. Sin embargo, la idea de los permisos aun se aplica.
Los
permisos para borrar archivos son independientes del archivo mismo. Si el
usuario tiene permiso de escritura en un directorio, puede borrar archivos de
el, aun los que estén protegidos contra escritura.
Un
archivo posee varios componentes : un nombre, contenido e información
administración como permiso y fechas de modificación. La información
administrativa esta almacenada en el “ nodo-i ”( en ingles muchas veces se usa
inodo ( sin guión ) en vez de i-nodo ), junto con datos esenciales para el
sistema tales como su longitud, la región del disco en la que se encuentra
almacenado el contenido del archivo y otros elementos.
Existen
tres fechas en un i-nodo: la fecha en la que se hizo la ultima modificación (
escrita ) al contenido del archivo, la fecha en la que dicho contenido fue
usado ( leído o ejecutado ) por ultima vez y la fecha en la que el i-nodo fue
alterado por ultima vez, por ejemplo, para definir los permisos.
El
nombre de archivo en un directorio se llama liga ( link ) ya que une un nombre
en la jerarquía de directorio al nodo-i y, en consecuencia, a los datos. El
mismo numero-i puede aparecer en mas de un directorio.
Por lo
tanto el nodo-i es un registro que almacena información sobre el archivo
determinado y contiene:
1)
Identificación
de usuario y de grupos de archivos.
2)
Instantes
del ultimo acceso y de la ultima modificación.
3)
Contador
con él numero de HORD-LINK al archivo.
4)
El
tipo de archivo.
5)
15
apuntadores a bloques de disco.
Los
primeros 12 bloques apuntan a bloques directos, o sea que se puede referenciar inmediatamente
a 12 directorios de bloques de datos de archivos ( ya que existe una copia del
nodo-i en memoria principal, mientras el archivo esta abierto ).
Los
siguientes tres apuntan a bloques indirectos ( del tamaño del bloque grande ):
-
El
primero es la dirección de un bloque indirecto simple ( bloques de direcciones
de bloques de datos )
-
El
segundo apunta a un bloque indirecto doble ( bloque de direcciones de bloques
que apuntan a bloques de datos )
-
El
tercero apunta a un bloque indirecto triple ( no se lo necesita )
Si el
primer carácter del nombre del camino es “/ ” ( slash ) es el directorio raiz,
sino el directorio de partida es el proceso actual. El final es el nombre de un
archivo, se realiza el proceso en busca de este nombre y si no se lo encuentra,
se emite un mensaje de error.
Par los
archivos no en disco se designan controladores apropiados para manejar su
entrada/salida.
Se
utiliza para indexar en una tabla de archivos abiertos el proceso actual. Cada
entrada en la tabla contiene unos apuntados a una estructura de archivos, que a
su vez apunta al nodo-i.
La
estructura del nodo-i es un copia en memoria que hay en disco, con campos
extras.
El UNIX
al estar estructurado en árbol se forma una jerarquía de directorios que para
un sistema seria:
/
Raíz del sistema de archivo.
/bin
Programas esenciales en forma ejecutable
/dev Archivos de dispositivos.
/etc
Sistemas diversos.
/etc/motd Mensaje
del dia al inicio de sesión.
/etc/passwd Archivos de
contraseñas.
/lib
Bibliotecas esenciales, etc.
/tmp
Archivos temporales, desaparecen cuando se reanuda el sistema.
/unix
Forma ejecutable del sistema operativo.
/usr
Sistemas de archivos del usuario.
/usr/adm
Administración del sistema, información contable, etc.
/usr/bin Binarios del usuario.
/usr/dict
Diccionario ( words ) y soporte de spell ( 1 ) etc.
Los
directorios se crean mediante la llamada al sistema mkdir y se pueden eliminar
mediante rmdir. El directorio actual se cambia mediante chdir.
Como lo indica su nombre, /dev contiene archivos de dispositivos.
Una de
las mejores ideas del sistema UNIX es la manera en que trata los periféricos (
discos, unidades de cinta, impresoras, terminales, etc. ).Por ejemplo, en lugar
de tener rutinas del sistema especiales para leer cintas magnéticas, existe
u archivo llamado /dev/mt0 (
dependiendo esto también de las costumbres locales )
Dentro
del núcleo, las referencias a ese archivo se convierten en comandos de hardware
para acceder la cinta, así, si un programa lee /dev/mt0. Obtiene el contenido
de una cinta montada en una unidad de cinta.
La
creación de un SF puede hacerse en 6 etapas:
1-
Dar
fromateo al soporte físico con el mandato iv o format.
2-
Crear
al SF con mkfs.
3-
Montar
el SF con el mandato mount.
4-
Crear
al directorio /lost+found.
5-
Dar
nombre al SF con el mandato labelit.
6-
Dar
formato a un volumen.
El sistema de entrada/salida se divide en dos
sistemas complementarios: el estructurado por bloques y el estructurado por
caracteres. El primero se usa para manejar cintas y discos magnéticos, y emplea
bloques de tamaño fijo (512 o 1024 bytes) para leer o escribir. El segundo se
utiliza para atender a las terminales, líneas de comunicación e impresoras, y
funciona byte por byte.
En general, el sistema Unix
emplea programas especiales (escritos en C) conocidos como manejadores (drivers)
para atender a cada familia de dispositivos de E/S. Los procesos se comunican
con los dispositivos mediante llamadas a su manejador. Además, desde el punto
de vista de los procesos, los manejadores aparecen como si fueran archivos en
los que se lee o escribe; con esto se logra gran homogeneidad y elegancia en el
diseño.
Cada dispositivo se
estructura internamente mediante descriptores llamados número mayor, número
menor y clase (de bloque o de caracteres). Para cada clase hay un conjunto de
entradas, en una tabla, que aporta a los manejadores de los dispositivos. El
número mayor se usa para asignar manejador, correspondiente a una familia de
dispositivos; el menor pasa al manejador como un argumento, y éste lo emplea
para tener acceso a uno de varios dispositivos físicos semejantes.
Las rutinas que el sistema
emplea para ejecutar operaciones de E/S están diseñadas para eliminar las
diferencias entre los dispositivos y los tipos de acceso. No existe distinción
entre acceso aleatorio y secuencial, ni hay un tamaño de registro lógico
impuesto por el sistema. El tamaño de un archivo ordinario está determinado por
el número de bytes escritos en él; no es necesario predeterminar el tamaño de
un archivo.
El sistema mantiene una
lista de áreas de almacenamiento temporal (buffers), asignadas a los
dispositivos de bloques. El Kernel usa estos buffers con el objeto de reducir
el tráfico de E/S. Cuando un programa solicita una transferencia, se busca
primero en los buffers internos para ver si el bloque que se requiere ya se
encuentra en la memoria principal (como resultado de una operación de lectura
anterior). Si es así, entonces no será necesario realizar la operación física
de entrada o salida.
Existe todo un mecanismo de
manipulación interna de buffers (y otro de manejo de listas de bytes),
necesario para controlar el flujo de datos entre los dispositivos de bloques (y
de caracteres) y los programas que los requieren.
Por
último, y debido a que los manejadores de los dispositivos son programas
escritos en lenguaje C, es relativamente fácil reconfigurar el sistema para
ampliar o eliminar dispositivos de E/S en la computadora, así como para incluir
tipos nuevos.
ENTRADA Y SALIDA
DEL SISTEMA UNIX.
Las
rutinas más sencillas de entrada y salida se llaman getchar y putchar. Cada llamada getchar extrae el siguiente
carácter de la entrada estándar, que puede ser un archivo, una interconexión o
la terminal: el programa no sabe cual. De modo analogo, putchar pone el
carácter c en la salida estándar, que también es la terminal por default.
La
función printf realiza la conversión
del formato de salida. Las llamadas a printf y putchar pueden intercalarse en
cualquier orden; la salida aparecera en el orden de las llamadas. Se da una
funcion correspondiente scanf para la
conversión del dato de entrada; leera la entrada estandar y la dividira en
cadenas, en numeros,etc.
Getchar
devuelve el siguiente byte de la entrada, o el valor EOF cuando encuentra el
fin de archivo (o un error). EOF no es un byte del archivo.
Acceso a archivos:
Antes de
leer o escribir un archivo, hay que abrirlo con la función estándar fopen. Esta función toma un nombre de
archivo, hace unos manejos internos y ajustes con el núcleo y devuelve un
nombre interno que se empleara en las siguientes operaciones con el archivo.
Este nombre interno es en realidad un
apuntador, denominado apuntador a archivo, a una estructura que contiene
información sobre el archivo; por ejemplo, la localización de un buffer, la
posición actual del carácter en el buffer, si el archivo esta siendo elido o
escrito y cosas parecidas. Una de las definiciones que se consiguen al incluir
<studio.h> es la estructura llamada FILE.
La declaración de un apuntador a archivo es:
FILE
*fp; (Esta declaración indica que fp es un apuntador
a FILE).
La
funcion fopen devuelve un apuntador
a FILE; la llamada a fopen en un programa es:
Char * name, * mode;
fp = fopen(name, mode);
El
primer argumento de fopen es el nombre del archivo, en forma de una cadena de caracteres.El
segundo argumento indica el uso que se
pretende dar al archivo; los modos son leer("r"),
escribir("w") y anexar("a").
Si un
archivo que se abre para escribirlo o anexarlo, pero no existe ,se crea este en
caso de ser posible, será un error intentar leer este archivo inexistente, lo
mismo que intentar leer o escribir un archivo cuando no se tiene acceso. Si
existe un error fopen devolverá el valor del apuntador invalido NULL(suele
definirse como (char*) 0, en <studio.h>).
Para
poder leer o escribir el archivo una vez abierto, se dispone n de varias
posibilidades, siendo getc y putc las mas sencillas.
Getc extrae el siguiente carácter de un archivo.
C=getc(fp)
Coloca
en c el siguiente carácter del archivo al cual se refiere fp; devuelve EOF al
llegar al fin del archivo. Putc es analogo a getc.
Putc pone el carácter c en el archivo fp.
Putc(c,fp)
Getc y putc
devuelven EOF cuando ocurre un error.
Al
iniciar un programa, ya están abiertos tres archivos con sus apuntadores a
archivo, estos archivos son entrada estándar, salida estándar y salida de error
estándar; los apuntadores correspondientes son stdin, stdout, y stderr.Estos
apuntadores se declaran en <studio.h> , pueden usarse en cualquier lugar
donde se encuentre un objeto FILE*. Como no son variables sino constantes no
podemos asignarles valores.
Algunas definiciones de
<studio.h>
Stdin (entrada estandar)
Stdout (salida estándar)
Stderr (error estándar)
EOF (fin del archivo, generalmente -1)
NULL (apuntador invalido; generalmente 0)
FILE (se usa para declarar apuntadores a archivos)
BUFSIZ (indica tamaño del buffer de E/S a menudo 512 o
1024)
Getc (fp) (regresa un carácter del flujo de datos fp)
Getchar
() getc(stdin)
Putc (c, fp) (pone el carácter c en el flujo de datos
fp)
Putchar
(c) putc(c,stdout)
Feof (fp) (no cero cuando hay fin de archivo en el
flujo de datos fp)
Ferror (fp) (no cero cuando hay un error en el flujo de
datos fp descriptor de archivo para el
flujo de datos fp.
Cuando un
archivo es largo y el usuario esta ligado a su sistema por medio de una
conexión de alta velocidad, cat produce la salida demasiado rapida para
leerla .
Sea un
programa p que muestre el contenido
de un archivo una pantalla por vez, espere una respuesta del usuario después de
cada una y luego pase a la siguiente, (p
es una abreviatura de un programa utilizado con frecuencia), p lee los archivos nombrados como
argumentos o su entrada estándar:
$ p vis.c
...
$ grep ' # define ' *.[ch] {p}
...
$
El
diseño consiste en imprimir la entrada en pequeños bloques.Un tamaño adecuado
es 22 líneas , una manera sencilla en que p
indica al usuario que esta listo consiste en no imprimir la ultima nueva-linea
de cada bloque de 22 líneas. El cursor hará una pausa en el extremo derecho del
renglón y no en el margen izquierdo. Cuando el usuario oprima la tecla RETURN,
se proporcionara la nueva-linea faltante y entonces el siguiente renglón
aparecerá en el lugar adecuado. Si el usuario teclea ctl-d o q al final de la
pantalla, p terminara.
La
rutina efopen encierra una operación muy común; trata de abrir un
archivo; sino es posible, imprime un mensaje de error y termina.
A BUFSIZ se lo definió como el tamaño del buffer de entrada. Fgets(buf, size, fp) extrae la siguiente línea de entrada de fp, hasta incluir una nueva-linea, la
coloca en el buffer y agrega un \ 0 terminador.
La
función strlen regresa la longitud de una cadena ; la usamos para sacar la
nueva-linea rezagada del ultimo renglón de entrada. Fputs(buf, fp) escribe la cadena buf en el archivo fp. La
llamada a fflush al final de la
pagina obliga a vaciar el buffer de salida.
La tarea
de leer la respuesta del usuario despues de desplegar cada pagina se delega a
una rutina llamada ttyin. Esta rutina
no puede leer de la entrada estándar ya que debe funcionar aun cuando su
entrada provenga de una archivo o interconexión.
Sobre errores y depuración.
La única
manera de escribir código sin errores consiste en procurarproducir un diseño
limpio y sencillo, programarlo cuidadosamente y mantenerlo claro al irlo
modificando.
Hay
varias herramientas del UNIX que sirven para encontrar errores.
Para
ejemplificar como funcionan examinemos las función pica que contiene un error:
Pick(s) / ofrecer
opcion de s */
Char * s;
{
fprint
("%s?",s);
if (ttuin ( ) == ' y ' )
printf
("%s\ n " , s);
}
Si la compilamos y ejecutamos, que ocurre?
$ cc pick.c -
o pick
$ pick * . c
intentelo
memory fault -
core dumped desastre!!!
$
"Error de Memoria" (memory fault) significa que el programa intento referenciar a un área de
memoria a la que no tiene permiso.
"Error en el bus " (bus error) es otro diagnostico de significado similar,
provocado a menudo al examinar una cadena no terminada correctamente.
"Vaciado de memoria" (Core dumped) significa que
el núcleo guardo el estado de la ejecución del programa en un archivo llamado core dentro del directorio actual.
Hay dos
programas que permiten examinar los restos del programa adb y sdb. Como la mayoria
de los depuradores de errores, son crípticos, complicados e indispensables adb viene en la séptima edición; sdb esta disponible en versiones mas
recientes del sistema.
fp =
fopen abrir archivo, "r": leer
; "w": escribir ; "a": anexar
c =
getc ( fp ) extraer carácter
putc (
c, fp ) introducir carácter
ungetc
(c, fp ) introducir un nuevo carácter en el archivo
de entrada fp; al
máximo 1 char puede
introducirse nuevamente a la vez.
Scanf
introducir caracteres .
Retorna EOF o numero de campos
convertidos
Fscanf lee de archivo fp
Sscanf lee de
cadena
Printf da formato
Fprintf imprime en
archivo
Sprintf imprime en cadena
Fgets introduce al máximo n caracteres en s a
partir de fp.
Fputs imprime una cadena en un archivo
Fflush pone en el archivo cualquier salida manejada
por buffer
Fclose cierra el archivo
Fp = popen
abre una interconexión con
el comando
Pclose cierra la interconexión
System
ejecuta un comando y espera la terminación
Redireccionamiento de E/ S
El error
estandar1 se invento para que los mensajes de error aparecieran siempre en la
terminal.
Todo
archivo tiene 3 archivos estándar, creados cuando este comienza a ejecutarse y
numerados conenteros pequeños llamados descriptores de archivos. La entrada
estándar 0 (cero), y la salida estándar 1 (uno), que son frecuentemente
redirigidos de archivos e interconexiones y hacia ellos. El ultimo con nro. 2,
es la salida de error estándar y normalmente se dirige a la terminal.
Algunas
veces los programas producen salida en el error estándar aun cuando funcionan
correctamente.
Tabla de redireccionamiento de E/
S de Shell.
>
file dirige salida estándar
o archivo
>>
file anexa salida estándar o
archivo
<
file toma salida estándar o archivo
p1 /
p2 conecta salida estándar dl
programa p1 con la entrada p2
^ sinónimo obsoleto de "/"
n >
file dirige la entrada del
descriptor de archivo n a archivo
n
>> file anexa salida del
descriptor de archivo n a archivo
n >
& mezclar la entrada del
descriptor de archivo n con el descriptor de archivo n
<<
s documento presente :
tomar la entrada estándar hasta el siguiente s al inicio
de una linea.
<<\
s documento presente sin
sustitución
<<
's' documento presente sin
sustitución
El nivel
mas bajo de E/S es una entrada directa al SO. Un archivo lee o escribe archivos
en porciones de tamaño adecuado. El núcleo mete los datos en buffers en
porciones que concuerdan con los dispositivos periféricos y optimiza el uso de
los periféricos entre los usuarios.
Descriptores de archivos.
Toda la
E/S se efectúa leyendo a escribiendo archivos, ya que todos los periféricos,
incluyendo la terminal, son archivos en el sistema de archivos. Esto significa
que una sola interfaz maneja todas las comunicaciones entre el programa y los
dispositivos periféricos.
En el caso más general, antes de leer o escribir un archivo, es necesario comunicar al sistema del intento; este proceso se conoce como abrir un archivo. Si se va a escribir en un archivo, puede ser necesario crearlo. El sistema revisa el permiso para hacerlo (existe el archivo) Tiene permiso de acceso?) , y si todo va bien regresa un entero no negativo llamado descriptor de archivo. Siempre que se haga E/S en el archivo, se utiliza el descriptor de archivo para identificarlo y, no el nombre.
Filtros.
Los filtros
comparten un diseño común. Cada uno escribe sobre su salida estándar el
resultado de procesar los archivos dados como argumentos o bien la entrada
estándar si no se dan los argumentos. Estos especifican la entrada pero nunca
la salida de modo que la salida de un comando siempre puede introducirse en una
interconexión.
Los
mensajes de error se escriben sobre el error estándar y, en consecuencia, no
desaparecen a lo largo de una interconexión.-
![]()
Número de visitantes actuales disponible desde el 14/07/2002:
Autor: lrmdavid@exa.unne.edu.ar
Ó FACENA - http://exa.unne.edu.ar
Servicios WEB: webmaster@exa.unne.edu.ar