Llamadas al Sistema en UNIX. - Universitat Jaume Iredondo/so/Capitulo1_IS11_llamadas.pdf ·...

21
Sistemas Operativos (IS11) – Tema 1 57 Gestión de ficheros: creat, open, read, write, close. Un fichero en UNIX: Es una secuencia de Byte sin formato, se accede a ellos de forma “directa”. La interpretación del contenido depende de las variables que use para lectura y escritura (enteros, caracteres,..). Existe un puntero que indica la posición del siguiente byte a leer o escribir, se actualiza tras cada operación. Tiene asociados unos permisos: rwxrwxrwx (usuario, grupo, otros) que se representan como un número en octal Ejemplo: rwxrw-r-- será: 0764 Llamadas al Sistema en UNIX. Sistemas Operativos (IS11) – Tema 1 58 Un proceso o programa tiene asignada una “tabla de descriptores de ficheros”. La tabla tiene un tamaño de 20 elementos. El descriptor de fichero es un número entero (0-19) que tiene asociado un fichero. El proceso accede a un fichero a través de un “descriptor de ficheros”. Un proceso sólo puede usar a la vez 20 ficheros. Inicialmente están asignadas las posiciones: 0: entrada estándar, 1: salida estándar, 2: salida de error estándar. Llamadas al Sistema en UNIX. 0 1 2 19

Transcript of Llamadas al Sistema en UNIX. - Universitat Jaume Iredondo/so/Capitulo1_IS11_llamadas.pdf ·...

Sistemas Operativos (IS11) – Tema 1 57

• Gestión de ficheros: creat, open, read, write, close.– Un fichero en UNIX:

• Es una secuencia de Byte sin formato, se accede a ellos de forma “directa”.

• La interpretación del contenido depende de las variables que use para lectura y escritura (enteros, caracteres,..).

• Existe un puntero que indica la posición del siguiente byte a leer o escribir, se actualiza tras cada operación.

• Tiene asociados unos permisos: rwxrwxrwx (usuario,grupo, otros) que se representan como un número en octal

• Ejemplo: rwxrw-r-- será: 0764

Llamadas al Sistema en UNIX.

Sistemas Operativos (IS11) – Tema 1 58

– Un proceso o programa tiene asignada una “tabla de descriptores de ficheros”.

• La tabla tiene un tamaño de 20 elementos.• El descriptor de fichero es un número entero (0-19) que

tiene asociado un fichero.• El proceso accede a un fichero a través de un “descriptor de

ficheros”.• Un proceso sólo puede usar a la vez 20 ficheros.• Inicialmente están asignadas las posiciones:

• 0: entrada estándar, • 1: salida estándar, • 2: salida de error estándar.

Llamadas al Sistema en UNIX.

012

19

Sistemas Operativos (IS11) – Tema 1 59

– Creación de nuevos ficheros: creat.• Sintaxis: #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 tiene permisos de escritura da un error.

• Sino existe:– Lo crea y añade permisos de escritura.

• Devuelve un entero:– Sino hay error: entre 0 y 19 (el descriptor del fichero). Devolverá el

más bajo que este libre (no asociado).– Si hay error: un número negativo.

• Ejemplos: fd=creat(“prueba”,0666);fd=creat(“/usr/prácticas/hola/prueba.c”,0600);

Llamadas al Sistema en UNIX.

Sistemas Operativos (IS11) – Tema 1 60

– Escritura de datos en un fichero: write.• Sintaxis: #include <unistd.h>

size_t write(desc_fich,dato,n_bytes);int desc_fich;const void *dato;size_t n_bytes;

• Devuelve:– El número de caracteres que ha podido escribir (n_escritos).– Un valor negativo si ha ocurrido un error en la llamada.

• Ejemplos: int n_escritos, fprueba;fprueba =creat(“fprueba”,0666);n_escritos= write(fprueba,”Esto es el dato del fichero\0”,28);

\0 es un carácter que delimita el final de una cadena

Llamadas al Sistema en UNIX.

Sistemas Operativos (IS11) – Tema 1 61

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

Llamadas al Sistema en UNIX.

#include <stdio.h>#include <fcntl.h>#include <unistd.h>

{ 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>

{ int i, fd, vector[10];fd=creat(“prueba”,0600);for (i=0;i<10;i++) vector[i]=i ;

exit(0);}

int main()

write(fd,vector,sizeof(vector));

!!!Faltaría cerrar el fichero!!!

int main()

#include <unistd.h>

b)

Sistemas Operativos (IS11) – Tema 1 62

fd=creat(“prueba”,0600);

– Cerrar un fichero: close.• Cuando no se va a acceder a los datos de un fichero se

cierra.• La utilidad es dejar libre un descriptor de ficheros.• Sintaxis: #include <unistd.h>

int close(descriptor_fichero);int descriptor_fichero;

• Devuelve:0 si se ha cerrado el fichero ó -1 en caso contrario.

• Ejemplo 2:

Llamadas al Sistema en UNIX.

#include <stdio.h>#include <fcntl.h>#include <unistd.h>

{ int fd, i, vector[10];

for (i=0;i<10;i++) vector[i]=i;

close(fd);

}

int main()

write(fd,vector,sizeof(vector));

exit(0);

Sistemas Operativos (IS11) – Tema 1 63

–Acceso a ficheros existentes: open.• Sintaxis: #include <fcntl.h>

int open(nombre, modo, permisos);const char *nombre;int modo, permisos;

• Devuelve:• -1 si se produce un error• El número de descriptor asociado al fichero abierto (el más

bajo libre en la tabla de descriptores).• Modos:

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/escrituraO_CREAT Sino existe el fichero se crea.O_TRUNC Si existe se borra la información 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);

Llamadas al Sistema en UNIX.

Sistemas Operativos (IS11) – Tema 1 64

– Lectura de datos de fichero: read.• Sintaxis: #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 quedará indicando el siguiente byte a

leer. Tras una operación se avanza el puntero.• Devuelve:

• El número de carácter leído (puede ser menor que bytes si se ha alcanzado el final del fichero).

• -1 si ha ocurrido un error en la llamada.

Llamadas al Sistema en UNIX.

Sistemas Operativos (IS11) – Tema 1 65

• Ejemplo 3: escribir en prueba de 0 a 9 y después leer el contenido de prueba e imprimir en pantalla.

Llamadas al Sistema en UNIX.

#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 número %d\n”,dato); }close(fd);exit(0);

}

Sistemas Operativos (IS11) – Tema 1 66

• Gestión de procesos: fork, wait, exit, execlp, execvp, pipe y dup.– Hay una versión jerárquica de procesos:

• Un proceso (hijo) aparece porque otro proceso lo genera (padre) mediante una llamada al sistema.

• Clases de llamadas:– Para generar y controlar procesos: fork, wait, exec.– Para reiniciar el código del proceso: execlp, execvp.– Para comunicación entre procesos: pipe, dup.

– Crear un nuevo proceso: fork.• Sintaxis: pid=fork();

int pid;• Si un proceso la ejecuta, se crea otro proceso que es réplica

de si mismo en memoria:– El código (programa) de los dos procesos es el mismo.

Llamadas al Sistema en UNIX.

Sistemas Operativos (IS11) – Tema 1 67

– Cada proceso continua la ejecución por separado (en el punto de la llamada).

– Todas las variables serán idénticas.– Los descriptores de ficheros son iguales.

• ¿Cómo 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.

• Ejemplo 4: #include <stdio.h>main(){ printf(“Inicio de test\n”);

if (fork() = = 0)printf(“Yo soy el hijo \n”);

elseprintf(“Yo soy el padre \n”);

exit(0);}

Llamadas al Sistema en UNIX.

Sistemas Operativos (IS11) – Tema 1 68

• Ejemplo 5: #include <stdio.h>int main(){ int i, j;

if (fork()!=0)

else

exit(0);}

Llamadas al Sistema en UNIX.

{ for (i=0;i<100;i++){ for (j=0;j<100000;j++);

printf(“Proceso padre. Indice i=%d\n”,i);}

}{ for (i=0;i<100;i++)

{ for (j=0;j<100000;j++);printf(“Proceso hijo. Indice i=%d\n”,i);

}}

Sistemas Operativos (IS11) – Tema 1 69

•Ejemplo 6: Dos procesos leen simultáneamente de un fichero #include <stdio.h>

........... int main(){ int i, j fd;

int dato;fd= open(“fprueba”,O_RDONLY);if (fork()!=0)

else

close(fd);exit(0);

}

Llamadas al Sistema en UNIX.

{ while (read(fd,&dato,sizeof(int))>0){ for (j=0;j<100000;j++); /*espera*/

printf(“Proceso padre. Dato =%d\n”,dato);}}

{ while (read(fd,&dato,sizeof(int))>0){ for (j=0;j<100000;j++); /*espera*/

printf(“Proceso hijo. Dato =%d\n”,dato); }}

Sistemas Operativos (IS11) – Tema 1 70

– Reiniciar el código del proceso: variantes de exec.• Permite cambiar el código del programa que se ejecuta:

– Cargará en memoria el código de un programa que estará en un fichero ejecutable.

– Lo carga sobre el código que existía en el proceso, sustituyéndolo.

– Una vez cargado comienza a ejecutarse.• ¿Qué ocurre con las instrucciones que hay después de exec

en el programa original?• Hay 6 llamadas exec. Veremos dos: execlp y execvp.• Sintaxis: #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;

Llamadas al Sistema en UNIX.

Sistemas Operativos (IS11) – Tema 1 71

• Sintaxis: #include <unistd.h>int execvp(fichero, argv);

const char *fichero;const char *argv[];

• Ejemplo: execlp(“ls”,”ls”,”-l”,NULL);execvp(“ls”,”ls -l”);

– Espera a que termine el proceso hijo: wait.• En ocasiones es necesario que el proceso padre espere a la

finalización de un proceso hijo.• Sintaxis: #include <sys/wait.h>

pid_t wait(estado);int *estado;

• Devuelve: El valor del pid del proceso hijo que acaba.• El proceso padre se desbloqueará cuando el hijo termine:

normal (exit(0)) o anormalmente.

Llamadas al Sistema en UNIX.

Sistemas Operativos (IS11) – Tema 1 72

• Ejemplo 7: #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);

}

Llamadas al Sistema en UNIX.

Sistemas Operativos (IS11) – Tema 1 73

– Terminación de un proceso: exit.• Sintaxis: #include <stdlib.h>

void exit(estado);int estado;

• Indica al S.O. la terminación del proceso. No es necesaria, si aconsejable:

– Cierra los descriptores de ficheros abiertos (Ver ejemplo 1).– Si el proceso padre ejecutó una llamada wait se activa.

– Comunicación entre procesos: pipe (tubería):• UNIX proporciona un mecanismo básico de comunicación

entre procesos: tuberías.– Es un tipo especial de fichero.– Tiene asociados dos descriptores de ficheros.– Por uno los procesos pueden escribir en la tubería.– Por el otro pueden leer de la tubería.

Llamadas al Sistema en UNIX.

Sistemas Operativos (IS11) – Tema 1 74

• Sintaxis: int pipe(descriptor);int descritor[2];

– descriptor[1]: descriptor para escribir datos en la tubería.– descriptor[0]: descriptor para leer datos de la tubería (en orden llegada) – Cuando se cierra descriptor[1] se introduce un EOF.

• Ejemplo 8: Escribir y leer en una tubería

Llamadas al Sistema en UNIX.

#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]);prinf(“Datos escritos en la tubería\n”);printf(“Se leen los datos\n”);while (read(fd[0],&dato,sizeof(int))>0) printf(“%d\n”,dato);close(fd[0]);exit(0);

}

Sistemas Operativos (IS11) – Tema 1 75

• Ejemplo 9: Escribir y leer en tubería

Llamadas al Sistema en UNIX.

#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));prinf(“Datos escritos en la tubería\n”);printf(“Se leen los datos\n”);while (read(fd[0],&dato,sizeof(int))>0) printf(“%d\n”,dato);

close(fd[0]);exit(0);

}

close(fd[1]);

!! Mal, no acaba !! hay que cerrar fd[1] para que read no se bloquee

Sistemas Operativos (IS11) – Tema 1 76

• Ejemplo10: #include <stdio.h> /*COMUNICACIÓN PADRE HIJO*/int main(argc,argv[])int argc; char *argv[];

{int tubería[2], dato, suma, estado;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));close(tuberia[1]); /* ¿Que pasa si la quito? */wait(&estado); /* ¿Que pasa si la quito ? */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;close(tuberia[0]); /* ¿Que pasa si la quito ? */prinf(“Suma calculada en el proceso hijo%d\n”,suma);exit(0);

}}

Llamadas al Sistema en UNIX.

Sistemas Operativos (IS11) – Tema 1 77

– Duplicación de descriptores de fichero: dup.

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

• Duplica el descriptor de fichero que se le pasa como parámetro.

• Devuelve el número del nuevo descriptor duplicado (tendremos dos descriptores apuntando al mismo sitio):

• Utilizaría el descriptor de fichero de número más bajo para la copia.

Llamadas al Sistema en UNIX.

Sistemas Operativos (IS11) – Tema 1 78

• 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);

}

Llamadas al Sistema en UNIX.

Sistemas Operativos (IS11) – Tema 1 79

• Gestión 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.

Llamadas al Sistema en UNIX.

Sistemas Operativos (IS11) – Tema 1 80

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

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 vacío se reemplaza por FromPath.• Si es directorio no vacío no cambia el nombre y da error.• Devuelve:

• -1 en caso de error.• 0 en caso contrario.

• Errores:• Si no se tienen permisos de ejecución en los directorios de los caminos

(paths), permisos de escritura en los directorios o ficheros oportunos, etc.• Si algún parámetro está siendo usado al mismo tiempo por el sistema.• Si ToPath especifica un directorio no vacío, FromPath es directorio y

ToPath no ó FromPath es fichero y ToPath no.

Llamadas al Sistema en UNIX.

Sistemas Operativos (IS11) – Tema 1 81

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

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 dirección inversa. El valor de offset está limitado por OFF_MAX.

• Whence especifica cómo interpretar Offset para mover el puntero del fichero especificado por FileDescriptor. Será uno de los siguientes valores que están definidos en el fichero /usr/include/unistd.h:

Llamadas al Sistema en UNIX.

Sistemas Operativos (IS11) – Tema 1 82

• SEEK_SET (ó 0) Mueve el puntero a la posición indicada por Offset.

• SEEK_CUR (ó 1) El Offset se usa como desplazamiento relativo desde la posición actual del puntero. La posición final del puntero será (actual + Offset).

• SEEK_END (ó 2) El Offset se usa como desplazamiento relativo desde el final del fichero. La posición final del puntero será (final de fichero + Offset).

• Devuelve:• Devuelve la localización final del puntero en bytes medida desde el

inicio del fichero.• Devuelve -1 en caso de error. .

• Errores:• Si FileDescriptor no corresponde a un fichero abierto.• Si FileDescriptor corresponde a una tubería abierta.• Si el offset sobrepasa el límite permitido definido en OFF_MAX.•

• En el fichero /usr/include/unistd.h están definidos los macros, tipos y subrutinas.

Llamadas al Sistema en UNIX.

Sistemas Operativos (IS11) – Tema 1 83

– Obtiene información referente a un fichero : stat.• Sintaxis: #include <sys/stat.h>

int stat ( Path, Buffer )const char *Path;struct stat *Buffer;

• Obtiene información referente a un fichero del cual damos su path.• Path especifica el nombre del fichero.• Buffer es un puntero a la estructura stat en el que se devuelve la

información.• No son necesarios permisos de lectura, escritura o ejecución para el

fichero.• En la ruta del Path todos los directorios deben tener permisos de

ejecución.• Detallamos aquí sólo los campos de la estructura stat más importantes.

Llamadas al Sistema en UNIX.

Sistemas Operativos (IS11) – Tema 1 84

• Detallamos aquí sólo los campos de la estructura stat más importantes.struct stat {dev_t st_dev; /* Dispositivo de ubicación del i_nodo */ino_t st_ino; /* Número de i_nodo */mode_t st_mode; /*Bits que indican tipo de fichero y permisos, en octal*/nlink_t st_nlink; /* Número de enlaces al fichero */uid_t st_uid; /* UID del propietario */gid_t st_gid; /* GID del propietario */off_t st_size; /* Tamaño del archivo en caracteres o bytes */time_t st_atime; /* Tiempo de último acceso */time_t st_mtime; /* Tiempo de última modificación */time_t st_ctime; /* Tiempo de último cambio en el i_nodo */}

Llamadas al Sistema en UNIX.

Sistemas Operativos (IS11) – Tema 1 85

• Devuelve:• -1 en caso de error.• 0 en caso contrario.

• Errores:• Permiso denegado en alguno de los directorios del path.• Un componente del path no es un directorio.• No existe el fichero.

• La estructura stat está definida en el fichero /usr/include/sys/stat.h.

• Los valores de algunos campos de stat están definidos en anubisen el fichero /usr/include/sys/mode.h y para linux ver: man 2 stat

• Los tipos de datos están definidos en el fichero /usr/include/sys/types.h.

Llamadas al Sistema en UNIX.

Sistemas Operativos (IS11) – Tema 1 86

– El campo st_mode viene representado por un número en octal de 6 dígitos• Digíto1) número octal que representa los permisos de otros sobre el fichero.• Digíto2) número octal que representa los permisos de grupo sobre el fichero.• Digíto3) número octal que representa permisos de usuario sobre el fichero. • Para averiguar los permisos se pueden utilizar las siguientes máscaras de bits

(los valores están puestos en octal), que se encuentran definidas en los diferentes ficheros que se incluyen al usar la llamada stat.

#define S_IRWXU 0000700 /* read,write,execute perm: owner */

#define S_IRUSR 0000400 /* read permission: owner */

#define S_IWUSR 0000200 /* write permission: owner */

#define S_IXUSR 0000100 /* execute/search permission: owner */

#define S_IRWXG 0000070 /* read,write,execute perm: group */

#define S_IRGRP 0000040 /* read permission: group */

#define S_IWGRP 0000020 /* write permission: group */

#define S_IXGRP 0000010 /* execute/search permission: group */

#define S_IRWXO 0000007 /* read,write,execute perm: other */

#define S_IROTH 0000004 /* read permission: other */

#define S_IWOTH 0000002 /* write permission: other */

#define S_IXOTH 0000001 /* execute/search permission: other */

Llamadas al Sistema en UNIX.

Sistemas Operativos (IS11) – Tema 1 87

• Digíto 4) No lo usaremos.• Digíto5 y 6) Contiene el tipo de fichero. Para averiguarlo se utilizan las

siguientes máscaras de bits (los valores están puestos en octal), que se encuentran definidas en los diferentes ficheros que se incluyen al usar la llamada stat.

• #define S_IFMT 0170000 /* type of file */

• #define S_IFREG 0100000 /* regular */

• #define S_IFDIR 0040000 /* directory */

• #define S_IFBLK 0060000 /* block special */

• #define S_IFCHR 0020000 /* character special */

• #define S_IFIFO 0010000 /* fifo */

– Para conocer un campo concreto de la estructura stat se puede utilizar máscaras junto con la operación & (se trata de un AND bit a bit) o usar macros. Ver man 2 stat.

– Al utilizar & es conveniente usar paréntesis para distinguir con claridad la prioridad de las operaciones que se utilicen.

Llamadas al Sistema en UNIX.

Sistemas Operativos (IS11) – Tema 1 88

• Ejemplo: Si queremos ver si un nombre que pasamos como primer argumento al programa es un fichero regular, tendríamos que poner al menos las siguientes líneas de programa

• {• struct stat campo;• .....• /*Sacar el contenido de la estructura*/• stat(argv[1], &campo);• /*Usar una máscara para ver si es fichero*/• 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] );• }

Llamadas al Sistema en UNIX.

Sistemas Operativos (IS11) – Tema 1 89

• Ejemplo: La línea if del ejemplo anterior puede realizarse utilizando el nombre dado para la máscara 0100000 en el fichero /usr/include/sys/stat.h (o consultar man 2 stat). Quedará entonces:

if ( ( (S_IFREG)&(campo.st_mode) ) = = (S_IFREG) )printf(“%s es un fichero regular \n”, argv[1] );

elseprintf(“%s no es un fichero regular \n”, argv[1] );

Llamadas al Sistema en UNIX.

Sistemas Operativos (IS11) – Tema 1 90

• Ejemplo: Finalmente, podemos utilizar una macro denominadaS_ISREG(m) definida en el fichero /usr/include/sys/stat.h (mode.h en anubis). Así dichas líneas quedarían: :

if ( S_ISREG ( campo.st_mode ) )printf(“%s es un fichero regular \n”, argv[1] );

elseprintf(“%s no es un fichero regular \n”, argv[1] );

• Las macros definidas son:S_ISFIFO(m) tipo de fichero fifoS_ISDIR(m) tipo de fichero directorioS_ISCHR(m) tipo de fichero de caracteres especialesS_ISBLK(m) tipo de fichero de bloques especialesS_ISREG(m) tipo de fichero regular

Llamadas al Sistema en UNIX.

Sistemas Operativos (IS11) – Tema 1 91

– Crea un directorio: mkdir.• Sintaxis: #include <stdio.h>

int mkdir (Path, Mode);const char * Path; mode_t Mode;

• Crea un nuevo directorio con los bits de permisos indicados en Mode.• Path especifica el nombre del nuevo directorio.• Mode especifica la máscara de lectura, escritura y ejecución para

usuario, grupo y otros con la que se creará el nuevo directorio (en octal).• Devuelve:

• -1 en caso de error.• 0 en caso contrario.

• Errores:• No se tienen los permisos adecuados para crear el directorio.• El nombre dado existe como fichero.• La longitud del Path es demasiado larga.• Algún componente del Path no es un directorio o no existe.

Llamadas al Sistema en UNIX.

Sistemas Operativos (IS11) – Tema 1 92

– Borra un directorio: rmdir.• Sintaxis: #include <stdio.h>

int rmdir (Path);const char * Path;

• Borra el directorio especificado en Path. Para ello hay que tener permiso de escritura en el directorio padre de Path.

• Path especifica un nombre de directorio.• Devuelve:

• -1 en caso de error.• 0 en caso contrario.

• Errores:• No se tiene permiso de escritura en el directorio padre de Path.• El directorio no está vacío.• La longitud de Path excede la permitida.• No existe el directorio.• Uno componente de Path no es directorio.• El directorio se refiere a un punto en el que hay montado un dispositivo.

Llamadas al Sistema en UNIX.

Sistemas Operativos (IS11) – Tema 1 93

– Cambiar el directorio de trabajo: chdir.• Sintaxis: #include <stdio.h>

int chdir (Path);const char * Path;

• Cambia el directorio de trabajo actual por el directorio indicado en Path• Path especifica el nombre del directorio donde se desea cambiar• Devuelve:

• -1 en caso de error.• 0 en caso contrario.

• Errores:• El acceso al nuevo directorio no está permitido (no se tienen permisos

adecuados)• Path no es un directorio.

Llamadas al Sistema en UNIX.

Sistemas Operativos (IS11) – Tema 1 94

Ejercicio 12.-En una base de datos (fichero llamado base) tenemos el formato que se describe a continuación. Los registros (de 2 campos) son de longitud fija, 64 bytes. El primer campo tiene formato de número entero (4 bytes) y almacena un entero que 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. El formato sería el siguiente:

Realizar un programa en C que usando llamadas al sistema lea, de manera adecuada, el fichero base que represente la base de datos anterior e imprima en pantalla en diferentes líneas los nombres que contiene.

Llamadas al Sistema en UNIX.

8 Mercedes6 Carlos7 Julieta

Sistemas Operativos (IS11) – Tema 1 95

Llamadas al Sistema en UNIX.

#include <stdio.h>#include <unistd.h>#include <fcntl.h>main(){ int fd, n, i, mueve, n_read, pos; dato, leidos;

fd= open(“base”, 0); /*abrir base para leer*/

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 tamaño pos*/dato[pos]= “\0”; /*fin de nombre leido*/printf(“%s\n”, dato); /*imprimir nombre*/mueve=64*i; /*puntero al siguiente registro*/

close(fd); /*cerrar fichero*/}

char dato[60];

n= lseek(fd, 0, 0); /*posicionar en primer dato*/

n=lseek(fd, mueve,0);}

Sistemas Operativos (IS11) – Tema 1 96

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 también imprimir la siguiente información:-tamaño del mismo-permisos que tenga habilitados-tiempo de la ultima modificación (usar ctime)

Ejemplo de ejecución:pepe es ficherode tamaño 512 bytespermiso de lectura para propietariopermiso de escritura para propietariopermiso de ejecución para el grupose modificó en Tue Nov 9 18:26:38 2001

Llamadas al Sistema en UNIX.

Sistemas Operativos (IS11) – Tema 1 97

Llamadas al Sistema en UNIX.#include <stdio.h>#include <unistd.h>#include <time.h>main(argc, argv)int argc; char * argv[];{ struct stat campo;

printf(“%s es un directorio\n”, argv[1]);

if (S_ISREG(campo.st_mode)){ printf(“%s es un fichero\n”, argv[1]);

printf(“de tamaño %d \n”, campo.st_size);

if (((S_IRUSR)&(campo.st_mode))= =(S_IRUSR)) /*0000400*/printf(“De lectura para el propietario\n”);

if (S_ISDIR(campo.st_mode))

else

stat(argv[1], &campo);

if (((S_IWUSR)&(campo.st_mode))= =(S_IWUSR)) /*0000200*/printf(“De escritura para el propietario\n”);if (((S_IXUSR)&(campo.st_mode))= =(S_IXUSR)) /*0000100*/printf(“De ejecución para el propietario\n”);

/*PERMISOS PROPIETARIO*/

Sistemas Operativos (IS11) – Tema 1 98

Llamadas al Sistema en UNIX.

if (((S_IRGRP)&(campo.st_mode))= =(S_IRGRP)) /*0000040*/printf(“De lectura para el grupo\n”);if (((S_IWGRP)&(campo.st_mode))= =(S_IWGRP)) /*0000020*/printf(“De escritura para el grupo \n”);if (((S_IXGRP)&(campo.st_mode))= =(S_IXGRP)) /*0000010*/printf(“De ejecución para el grupo \n”);

}

/*PERMISOS GRUPO*/

if (((S_IROTH)&(campo.st_mode))= =(S_IROTH)) /*0000004*/printf(“De lectura para otros\n”);if (((S_IWOTH)&(campo.st_mode))= =(S_IWOTH)) /*0000002*/printf(“De escritura para otros \n”);if (((S_IXOTH)&(campo.st_mode))= =(S_IXOTH)) /*0000001*/printf(“De ejecución para otros \n”);

/*PERMISOS OTROS*/

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