Anda di halaman 1dari 11

Llamadas al Sistema en UNIX.

Gestin de ficheros: creat, open, read, write, close.


Un proceso o programa tiene asignada una: tabla de descriptores de ficheros La tabla tiene un tamao de 20 elementos. El descriptor de fichero es un nmero entero (0-19) que tiene asociado un fichero. El proceso accede a un fichero a travs de un: descriptor de ficheros Un proceso slo puede usar a la vez 20 ficheros. 0 Inicialmente estn asignadas las posiciones: 1 2 0: entrada estndar, 1: salida estndar, 2: salida de error estndar. 19 Creacin de nuevos ficheros: creat.
-Ejemplos:
fd=creat(prueba,0666); fd=creat(/usr/prcticas/hola/prueba.c,0600);

#include <fcntl.h> int creat (nombre, mode_t permisos); const char *nombre; mode_t permisos;

Si existe el fichero :
No modifica los permisos. Si tiene permiso de escritura borra el contenido, sino.. dara error.

Devuelve un entero:
Sino hay error: entre 0 y 19 (el descriptor del fichero). Devolver el mas bajo que este libre (no asociado)

Escritura de datos en un fichero: write.


#include <unistd.h> size_t write(desc_fich,dato,n_bytes); int desc_fich; const void *dato; size_t n_bytes;

Devuelve:
El nmero de caracteres que ha podido escribir (n_escritos).

Ejemplos:
int n_escritos, fprueba; fprueba =creat(fprueba,0666); n_escritos= write(fprueba,Esto es el dato del fichero\0,28); ## /0 = final de la cadena

Ejemplo 1: crear fichero y escribir en el del 0 al 9


a) b) #include <stdio.h> #include <fcntl.h> #include <unistd.h> int main() { int i, fd; fd=creat(prueba,0600); for (i=0;i<10;i++) write(fd,&i,sizeof(i)); exit(0); }
#include <stdio.h> #include <fcntl.h> #include <unistd.h> int main() { int i, fd, vector[10]; fd=creat(prueba,0600); for (i=0;i<10;i++) vector[i]=i ; write(fd,vector,sizeof(vector)); close(fd); exit(0); } !!!Faltara cerrar el fichero!!!

Cerrar un fichero: close.


#include <unistd.h> int close(descriptor_fichero); int descriptor_fichero;

La utilidad es dejar libre un descriptor de ficheros.

Acceso a ficheros existentes: open.


#include <fcntl.h> int open(nombre, modo, permisos); const char *nombre; int modo, permisos;

Devuelve: -1 si se produce un error o


El nmero de descriptor asociado al fichero abierto (el mas bajo libre en la tabla de descriptores).

O_RDONLY (0) El fichero se abre para lectura. El puntero en byte 0. O_WRONLY (1) El fichero se abre para escritura. Puntero en byte 0. O_RDWR (2) El fichero se abre en modo lectura/escritura O_CREAT Sino existe el fichero se crea. O_TRUNC Si existe se borra la informacin que contiene. O_EXCL Con O_CREAT la llamada falla si el fichero existe. O_APPEND El puntero del fichero apunta al final del mismo. Para activar varios modos a la vez se usa un OR. Ejemplos: fd=open(fichero,1|O_CREAT,0666);
fd=open(fichero,O_WRONLY|O_CREAT|O_TRUNC,0644);

Modos:

Lectura de datos de fichero: read.


#include <unistd.h> size_t read(fd, dato, bytes); int fd; const void *dato; size_t bytes;

Hay que abrir previamente el fichero. El puntero del fichero queda indicando el siguiente byte a leer. Tras una operacin se avanza el puntero.

Devuelve:
El nmero de carcter ledo (puede ser menor que bytes si se ha alcanzado el final del fichero). -1 si ha ocurrido un error en la llamada. #include <stdio.h> #include <unistd.h> #include <fcntl.h> int main() { int fd, i, vector[10], dato, leidos; fd= creat(prueba,0600); for (i=0;i<10;i++) vector[i]; write(fd,vector,sizeof(vector)); close(fd); fd= open(prueba,O_RDONLY); while ((leidos= read(fd,&dato,sizeof(int)))>0) { printf(Leido el nmero %d\n,dato); } close(fd); exit(0); }

escribir en prueba de 0 a 9

leer el contenido de prueba imprimir en pantalla

Gestin de procesos: fork, wait, exit, execlp, execvp, pipe y dup


Un proceso (hijo) aparece porque otro proceso lo genera ( padre) mediante: fork()
Para generar y controlar procesos: fork, wait, exec. Para reiniciar el cdigo del proceso: execlp, execvp. Para comunicacin entre procesos: pipe, dup.

Crear un nuevo proceso: fork.


pid=fork(); int pid;

Cmo se distingue entre el padre y el hijo?


fork() devuelve un entero:
Valdr cero en el hijo. Valdr el identificador del proceso hijo en el padre.

Si un proceso la ejecuta, se crea otro proceso que es rplica de si mismo en memoria:


El cdigo (programa) de los dos procesos es el mismo. Cada proceso continua la ejecucin por separado (en el punto de la llamada). Todas las variables sern idnticas. y los descriptores de ficheros tambien son iguales. if (fork() = = 0) printf(Yo soy el hijo \n); else printf(Yo soy el padre \n);

Dos procesos leen simultneamente de un fichero


#include <stdio.h> int main() { int i, j fd; int dato; fd= open(fprueba,O_RDONLY); if (fork()!=0) { while (read(fd,&dato,sizeof(int))>0) { for (j=0;j<100000;j++); /*espera*/ printf(Proceso padre. Dato =%d\n,dato);} } else { while (read(fd,&dato,sizeof(int))>0) { for (j=0;j<100000;j++); /*espera*/ printf(Proceso hijo. Dato =%d\n,dato); } } close(fd); exit(0); }

#include <stdio.h> int main() { int i, j; if (fork()!=0) { for (i=0;i<100;i++) { for (j=0;j<100000;j++); printf(Proceso padre. Indice i=%d\n,i); } } else { for (i=0;i<100;i++) { for (j=0;j<100000;j++); printf(Proceso hijo. Indice i=%d\n,i); } } } exit(0);

Reiniciar el cdigo del proceso: variantes de exec.


Cargar en memoria el cdigo de un programa que estar en un fichero ejecutable. Lo carga sobre el cdigo que exista en el proceso, sustituyendolo. Una vez cargado comienza a ejecutarse.

execlp
#include <unistd.h> int execlp(fichero,arg0,arg1,arg2, , argN, (char *)0); const char *fichero; const char *arg0; const char *arg1; const char *arg2; . const char *argN;

execvp
#include <unistd.h> int execvp(fichero, argv); const char *fichero; const char *argv[];

Ejemplos :

execlp(ls,ls,-l,NULL);

execvp(ls,ls -l);

Espera a que termine el proceso hijo: wait.


#include <sys/wait.h> pid_t wait(estado); int *estado; Devuelve: El valor del pid del proceso hijo que acaba.

El proceso padre esperara para desbloquearse hasta la finalizacion de un proceso hijo.


#include <stdio.h> int main() { int j, fd; int dato, estado; /* Diferencia ejemplo 6 */ fd= open(fprueba,O_RDONLY); if (fork()!=0) { while (read(fd,&dato,sizeof(int))>0) { for (j=0;j<100000;j++); printf(Proceso padre. Dato =%d\n,dato); } wait(&estado); /* Diferencia ejemplo 6 */ } else { while (read(fd,&dato,sizeof(int))>0) { for (j=0;j<100000;j++); printf(Proceso hijo. Dato =%d\n,dato); } } close(fd); exit(0); }

Terminacin de un proceso: exit. Cierra los descriptores de ficheros abiertos


#include <stdlib.h> void exit(estado); int estado; Si el proceso padre ejecut una llamada wait se activa.

Comunicacin entre procesos: pipe (tubera):


Es un tipo especial de fichero. Tiene asociados dos descriptores de ficheros.

int pipe(descriptor); int descritor[2];

descriptor[1]: descriptor para escribir datos en la tubera. (al cerrar descriptor[1] se introduce un EOF) descriptor[0]: descriptor para leer datos de la tubera (en orden llegada)

Escribir y leer en una tubera


#include <stdio.h> #include <unistd.h> int main() { int dato, fd[2]; pipe (fd); for (dato=0;dato<10;dato++) write( fd[1], &dato, sizeof(int) ); close(fd[1]); /* esta orden es necesaria porque hay que cerrar fd[1] para que read no se bloquee */ prinf(Datos escritos en la tubera\n); printf(Se leen los datos\n); while ( read( fd[0], &dato, sizeof(int) ) > 0 close(fd[0]); exit(0); } ) printf(%d\n,dato);

Comunicacion padre-hijo mediante tuberia


#include <stdio.h> int main(argc,argv[]) { int argc; char *argv[]; int dato, suma, estado, tuberia[2]; pipe(tuberia); if (fork()!=0) { /* proceso padre, escribe de 1 a dato */ close(tuberia[0]); dato=atoi(argv[1]); /* transforma argv[1] en entero */ for (i=1;i<=dato;i++) write(tuberia[1],&i,sizeof(int)); /* Que pasa si la quito? */ close(tuberia[1]); /* Que pasa si la quito ? */ wait(&estado); printf(El padre finaliza despues que el hijo\n); exit(0); } else { /* proceso hijo , suma de 1 a dato*/ close(tuberia[1]); suma = 0; while (read(tuberia[0],&dato,sizeof(int))>0) suma=suma+dato; /* Que pasa si la quito ? */ close(tuberia[0]); prinf(Suma calculada en el proceso hijo%d\n,suma); exit(0);
} }

Duplicacin de descriptores de fichero: dup.


#include <unistd.h> int dup(desc_fich); int desc_fich;

Devuelve el nmero del nuevo descriptor duplicado (tendremos dos descriptores apuntando al mismo sitio): Utilizara el descriptor de fichero de nmero ms bajo para la copia.

Ejemplo 11:
#include <stdio.h>
int main() {int fichero, duplicado, i dato, salir; fichero= creat(fprueba,0644); for (i=0;i<10;i++) write(fichero,&i,sizeof(int)); close(fichero); printf(Ya se ha creado el fichero\n); fichero=open(fprueba,O_RDONLY); printf(Abierto el fichero sobre descriptor: %d\n,fichero); duplicado= dup(fichero); printf(Duplicado sobre descriptor: %d\n,duplicado); salir= FALSE; while (!salir) {salir= (read(fichero,&dato,sizeof(int))==0); if (!salir) {printf(dato leido mediante fichero = %d\n,dato); salir= (read(duplicado,&dato,sizeof(dato))==0); if (!salir) printf(dato leido mediante duplicado = %d\n,dato); else printf(Final de fichero encontrado en duplicado\n); } else printf(Final de fichero encontrado en fichero\n); } close(fichero); close(duplicado); exit(0); }

Gestin de ficheros y directorios: remove, rename, lseek, stat, mkdir, rmdir y chdir.
Borrar un fichero: remove. Sintaxis: #include <stdio.h>
int remove (Filename); const char *Filename;

Borra el fichero llamado Filename El fichero no se borrar si est abierto cuando se utiliza la llamada remove. Si el fichero tiene varios links (enlaces duros) la cuenta de estos desciende en uno. Devuelve: cero en caso de que se haya podido borrar el fichero.
un valor no nulo en caso contrario.

Cambio el nombre de un directorio o fichero: Sintaxis: #include <stdio.h>

rename.

int rename (FromPath, ToPath); const char * FromPath, ToPath; FromPath identifica el fichero o directorio cuyo nombre se cambia. ToPath identifica el nuevo path. FromPath, ToPath deben ser ambos del mismo tipo (fich, o direc). Si ToPath es fichero o directorio vaco se reemplaza por FromPath. Si es directorio no vaco no cambia el nombre y da error.
-1 en caso de error. 0 en caso contrario.

Devuelve: Errores:

Por falta de permisos de ejecucin o de escritura en los directorios o ficheros oportunos.. etc Si algn parmetro est siendo usado al mismo tiempo por el sistema. Si ToPath es un directorio no vaco, FromPath es directorio y ToPath no FromPath es fichero y ToPath no.

Mover puntero de lectura o escritura de un fichero abierto: Sintaxis: #include <unistd.h>

lseek.

off_t lseek ( FileDescriptor, Offset, Whence) int FileDescriptor, Whence; off_t Offset; Posiciona el puntero de un fichero abierto cuyo descriptor sea FileDescriptor FileDescriptor. especifica el descriptor de un fichero abierto con la llamada open. Offset especifica el valor en bytes que se desplazar el puntero. Un valor negativo mueve en direccin inversa. El valor de offset est limitado por OFF_MAX. Whence especifica como unterpretar Offset para mover el puntero del fichero especificado por FileDescriptor. Ser uno de los valores q estn definidos en el fichero /usr/include/unistd.h:

SEEK_SET ( 0) Mueve el puntero a la posicion indicada por Offset. SEEK_CUR ( 1) El Offset se usa como desplazamiento relativo desde la posicin actual del puntero. La posicion final del puntero ser (actual + Offset). SEEK_END ( 2) El Offset se usa como desplazamiento relativo desde el final del fichero. La posicin final del puntero ser (final de fichero + Offset).

Devuelve: Errores:

- Devuelve la localizacion final del puntero en bytes medida desde el inicio del fichero. - Devuelve -1 en caso de error. .

Si FileDescriptor no corresponde a un fichero abierto. Si FileDescriptor corresponde a una tubera abierta. Si el offset sobrepasa el lmite permitido definido en OFF_MAX. En el fichero /usr/include/unistd.h estn definidos los macros, tipos y subrutinas.

Obtiene informacin referente a un fichero: stat. /* Path especifica el nombre del fichero */ Sintaxis: #include <sys/stat.h>
int stat ( Path, Buffer ) const char *Path; struct stat *Buffer; /* Buffer es un puntero a la estructura stat en el q se devuelve la informacin */ /* No son necesarios permisos de lectura, escritura o ejecucin para el fichero */

En la ruta del Path todos los directorios deben tener permisos de ejecucin. Detallamos aqu slo los campos de la estructura stat ms importantes. struct stat { dev_t st_dev; /* Dispositivo de ubicacin del i_nodo */ ino_t st_ino; /* Nmero de i_nodo */ mode_t st_mode; /* Bits que indican tipo de fichero y permisos, en octal */ nlink_t st_nlink; /* Nmero de enlaces al fichero */ uid_t st_uid; /* UID del propietario */ gid_t st_gid; /* GID del propietario */ off_t st_size; /* Tamao del archivo en caracteres o bytes */ time_t st_atime; /* Tiempo de ltimo acceso */ time_t st_mtime; /* Tiempo de ltima modificacin */ time_t st_ctime; /* Tiempo de ltimo cambio en el i_nodo */ } La estructura stat definida en ---> fichero /usr/include/sys/stat.h (mode.h en abubis) man 2 stat Los tipos de datos estn definidos en el fichero /usr/include/sys/types.h. El campo st_mode viene representado por un nmero en octal de 6 dgitos Digto1) nmero octal que representa los permisos de otros sobre el fichero. Digto2) nmero octal que representa los permisos de grupo sobre el fichero. Digto3) nmero octal que representa permisos de usuario sobre el fichero. Para averiguar los permisos se pueden utilizar las siguientes mscaras de bits (valores en octal) que se encuentran definidas en los diferentes ficheros que se incluyen al usar la llamada stat.
#define #define #define #define #define #define #define #define #define #define #define #define S_IRWXU S_IRUSR S_IWUSR S_IXUSR S_IRWXG S_IRGRP S_IWGRP S_IXGRP S_IRWXO S_IROTH S_IWOTH S_IXOTH 0000700 0000400 0000200 0000100 0000070 0000040 0000020 0000010 0000007 0000004 0000002 0000001 /* /* /* /* /* /* /* /* /* /* /* /* read,write,execute perm: owner */ read permission: owner */ write permission: owner */ execute/search permission: owner */ read,write,execute perm: group */ read permission: group */ write permission: group */ execute/search permission: group */ read,write,execute perm: other */ read permission: other */ write permission: other */ execute/search permission: other */

Digto 4) No lo usaremos. Digto5 y 6) Contiene el tipo de fichero. usaremos las mascaras de bits (valores en octal) que se encuentran definidas en los diferentes ficheros que se incluyen al usar la llamada stat.
#define #define #define #define #define #define S_IFMT S_IFREG S_IFDIR S_IFBLK S_IFCHR S_IFIFO 0170000 0100000 0040000 0060000 0020000 0010000 /* type of file */ /* regular */ /* directory */ /* block special */ /* character special */ /* fifo */

Para conocer un campo de la estructura stat se pueden utilizar mscaras junto con la operacion & (se trata de un AND bit a bit) o usar macros. para ver si un nombre q pasamos como primer argumento al programa es un fichero regular, tendramos que poner almenos las siguientes lneas de programa { struct stat campo; ..... stat(argv[1], &campo); if ( ( ( 0100000)&(campo.st_mode) ) = = (0100000) ) printf(%s es un fichero regular \n, argv[1] ); else printf(%s no es un fichero regular \n, argv[1] ); }

/*Sacar el contenido de la estructura*/ /*Usar una mscara para ver si es fichero*/

la linea if anteior = utilizar nombre dado para la mascara 0100000 en el fichero /usr/include/sys/stat.h if ( ( (S_IFREG)&(campo.st_mode) ) = = (S_IFREG) ) printf(%s es un fichero regular \n, argv[1] ); else printf(%s no es un fichero regular \n, argv[1] ); o utilizando la macro denominada S_ISREG(m) del fichero /usr/include/sys/stat.h (mode.h en anubis) if ( S_ISREG ( campo.st_mode ) ) printf(%s es un fichero regular \n, argv[1] ); else printf(%s no es un fichero regular \n, argv[1] ); Las macros definidas son: S_ISFIFO(m) tipo de fichero fifo S_ISDIR(m) tipo de fichero directorio S_ISCHR(m) tipo de fichero de caracteres especiales S_ISBLK(m) tipo de fichero de bloques especiales S_ISREG(m) tipo de fichero regular

Crea un directorio:

mkdir.
/* Path = nombre del nuevo directorio */ /* Mode = permisos del nuevo directorio (valores en octal) */

#include <stdio.h> int mkdir (Path, Mode); const char * Path; mode_t Mode;

Errores: La longitud del Path es demasiado larga. Borra un directorio:


#include <stdio.h> int rmdir (Path); const char * Path;

rmdir.
/* Path = nombre del directorio a borrar, requiere permiso de escritura) */

Errores: El directorio no est vaco. El directorio se refiere a un punto en el que hay montado un dispositivo. Cambiar el directorio de trabajo:
#include <stdio.h> int chdir (Path); const char * Path;

chdir.

/* Path = directorio a donde moveremos nuestro espacio de trabajo */


Path no es un directorio.

Errores:

No se tienen los permisos adecuados.

Ejercicio 12.-En una base de datos (fichero llamado base) tenemos el formato q se describe a continuacin. Los registros (de 2 campos) son de longitud fija, 64 bytes. El primer campo tiene formato de numero entero (4 bytes) y almacena un entero q da la longitud del nombre acumulado en el segundo campo. El segundo campo contiene el nombre asociado (caracteres) seguido por caracteres basura hasta un total de 60 bytes. 8 Mercedes 6 Carlos 7 Julieta leer fichero base (base de datos) anterior e imprimir en pantalla 1 nombre en cada linea
#include <stdio.h> #include <unistd.h> #include <fcntl.h> main() { int fd, n, i, mueve, n_read, pos; dato, leidos; char dato[60]; fd= open(base, 0); /*abrir base para leer*/ n= lseek(fd, 0, 0); /*posicionar en primer dato*/ for (i=1;i<4;i++) /* recorrer cada registros { n_read=read(fd,&pos,sizeof(int)); /*leer primer entero*/ n_read=read(fd, dato, pos); /*leer nombre de tamao pos*/ dato[pos]= \0; /*fin de nombre leido*/ printf(%s\n, dato); /*imprimir nombre*/ mueve=64*i; /*puntero al siguiente registro*/ n=lseek(fd, mueve,0); } close(fd); /*cerrar fichero*/ }

Ejercicio 13.-Realizar un programa en C que usando la llamada al sistema stat, nos imprima en pantalla si el nombre que se pasa como argumento es un fichero o es un directorio. En caso de ser fichero debe tambin imprimir la siguiente informacin: -tamao del mismo -permisos que tenga habilitados -tiempo de la ultima modificacin (usar ctime) Ejemplo de ejecucin: pepe es fichero de tamao 512 bytes permiso de lectura para propietario permiso de escritura para propietario permiso de ejecucin para el grupo se modific en Tue Nov 9 18:26:38 2001
#include <stdio.h> #include <unistd.h> #include <time.h> main(argc, argv) int argc; char * argv[]; { struct stat campo; stat(argv[1], &campo); if (S_ISDIR(campo.st_mode)) printf(%s es un directorio\n, argv[1]); else if (S_ISREG(campo.st_mode)) { printf(%s es un fichero\n, argv[1]); printf(de tamao %d \n, campo.st_size);
/*PERMISOS PROPIETARIO*/

if (((S_IRUSR)&(campo.st_mode))= =(S_IRUSR)) printf(De lectura para el propietario\n); if (((S_IWUSR)&(campo.st_mode))= =(S_IWUSR)) printf(De escritura para el propietario\n); if (((S_IXUSR)&(campo.st_mode))= =(S_IXUSR)) printf(De ejecucin para el propietario\n);
/*PERMISOS GRUPO*/

/*0000400*/ /*0000200*/ /*0000100*/

if (((S_IRGRP)&(campo.st_mode))= =(S_IRGRP)) printf(De lectura para el grupo\n); if (((S_IWGRP)&(campo.st_mode))= =(S_IWGRP)) printf(De escritura para el grupo \n); if (((S_IXGRP)&(campo.st_mode))= =(S_IXGRP)) printf(De ejecucin para el grupo \n);
/*PERMISOS OTROS*/

/*0000040*/ /*0000020*/ /*0000010*/

if (((S_IROTH)&(campo.st_mode))= =(S_IROTH)) printf(De lectura para otros\n); if (((S_IWOTH)&(campo.st_mode))= =(S_IWOTH)) printf(De escritura para otros \n); if (((S_IXOTH)&(campo.st_mode))= =(S_IXOTH)) printf(De ejecucin para otros \n);

/*0000004*/ /*0000002*/ /*0000001*/

printf(Se modifico en: %s \n, ctime(&campo.st_mtime)); } }

Anda mungkin juga menyukai