Llamadas al Sistema en UNIX. Llamadas al Sistema en by zwj23860

VIEWS: 2,141 PAGES: 21

									 Llamadas al Sistema en UNIX.

• 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




                     Sistemas Operativos (IS11) – Tema 1               57




 Llamadas al Sistema en UNIX.

   – 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,                 0
                                                       1
                • 1: salida estándar,                  2
                • 2: salida de error estándar.

                                                           19


                     Sistemas Operativos (IS11) – Tema 1               58
Llamadas al Sistema en UNIX.
 – 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);


                      Sistemas Operativos (IS11) – Tema 1                           59




Llamadas al Sistema en UNIX.

 – 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

                      Sistemas Operativos (IS11) – Tema 1                           60
Llamadas al Sistema en UNIX.
   Ejemplo 1: crear fichero y escribir en el del 0 al 9
   a)     #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);
          }
   b)      #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));
               exit(0);
           }
                    !!!Faltaría cerrar el fichero!!!
                        Sistemas Operativos (IS11) – Tema 1                     61




Llamadas al Sistema en UNIX.
 – 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: #include <stdio.h>
                            #include <fcntl.h>
                            #include <unistd.h>
                            int main()
                            { int fd, i, vector[10];
                                fd=creat(“prueba”,0600);
                                for (i=0;i<10;i++) vector[i]=i;
                                write(fd,vector,sizeof(vector));
                                close(fd);
                                exit(0);
                           }
                        Sistemas Operativos (IS11) – Tema 1                     62
Llamadas al Sistema en UNIX.
 –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/escritura
     O_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);

                    Sistemas Operativos (IS11) – Tema 1                     63




Llamadas al Sistema en UNIX.

 – 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.




                    Sistemas Operativos (IS11) – Tema 1                     64
 Llamadas al Sistema en UNIX.

       • Ejemplo 3: escribir en prueba de 0 a 9 y después leer el
         contenido de prueba e imprimir en pantalla.
                            #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                    65




 Llamadas al Sistema en UNIX.

• 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.

                     Sistemas Operativos (IS11) – Tema 1                    66
Llamadas al Sistema en UNIX.

        – 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”);
                          else
                                   printf(“Yo soy el padre \n”);
                          exit(0);
                        }

                   Sistemas Operativos (IS11) – Tema 1                     67




Llamadas al Sistema en UNIX.

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

                   Sistemas Operativos (IS11) – Tema 1                     68
Llamadas al Sistema en UNIX.
    • 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)
                           { 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);
                    }
                     Sistemas Operativos (IS11) – Tema 1                      69




Llamadas al Sistema en UNIX.
 – 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;
                     Sistemas Operativos (IS11) – Tema 1                      70
Llamadas al Sistema en UNIX.

     • 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.

                   Sistemas Operativos (IS11) – Tema 1                    71




Llamadas al Sistema en UNIX.
     • 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);
                   }


                   Sistemas Operativos (IS11) – Tema 1                    72
Llamadas al Sistema en UNIX.

 – 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.


                      Sistemas Operativos (IS11) – Tema 1                    73




Llamadas al Sistema en UNIX.
  • 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
                #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                    74
Llamadas al Sistema en UNIX.

   • Ejemplo 9: Escribir y leer en tubería
                     #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[1]);
                        close(fd[0]);
                        exit(0);
                      }

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

                         Sistemas Operativos (IS11) – Tema 1                   75




Llamadas al Sistema en UNIX.
 • 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);
                 }
             }
                         Sistemas Operativos (IS11) – Tema 1                   76
Llamadas al Sistema en UNIX.

 – 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.




                       Sistemas Operativos (IS11) – Tema 1                            77




Llamadas al Sistema en UNIX.
• 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);
          }

                       Sistemas Operativos (IS11) – Tema 1                            78
Llamadas al Sistema en UNIX.

• 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.


                       Sistemas Operativos (IS11) – Tema 1                           79




Llamadas al Sistema en UNIX.

 – 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.

                       Sistemas Operativos (IS11) – Tema 1                           80
 Llamadas al Sistema en UNIX.

– 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:



                          Sistemas Operativos (IS11) – Tema 1                         81




 Llamadas al Sistema en UNIX.

          • 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.

                          Sistemas Operativos (IS11) – Tema 1                         82
Llamadas al Sistema en UNIX.

 – 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.




                      Sistemas Operativos (IS11) – Tema 1                  83




Llamadas al Sistema en UNIX.

   • 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 */
   }



                      Sistemas Operativos (IS11) – Tema 1                  84
Llamadas al Sistema en UNIX.

     • 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 anubis
       en 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.


                       Sistemas Operativos (IS11) – Tema 1                         85




Llamadas al Sistema en UNIX.

–   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 */


                       Sistemas Operativos (IS11) – Tema 1                         86
Llamadas al Sistema en UNIX.

• 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.


                        Sistemas Operativos (IS11) – Tema 1                 87




Llamadas al Sistema en UNIX.

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


                        Sistemas Operativos (IS11) – Tema 1                 88
Llamadas al Sistema en UNIX.

• 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] );
   else
      printf(“%s no es un fichero regular \n”, argv[1] );




                       Sistemas Operativos (IS11) – Tema 1                89




Llamadas al Sistema en UNIX.

• Ejemplo: Finalmente, podemos utilizar una macro denominada
  S_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] );
   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

                       Sistemas Operativos (IS11) – Tema 1                90
Llamadas al Sistema en UNIX.

– 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.



                            Sistemas Operativos (IS11) – Tema 1                         91




Llamadas al Sistema en UNIX.

 – 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.



                            Sistemas Operativos (IS11) – Tema 1                         92
Llamadas al Sistema en UNIX.

 – 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.




                      Sistemas Operativos (IS11) – Tema 1                        93




Llamadas al Sistema en UNIX.

 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:
               8            Mercedes
               6            Carlos
               7            Julieta

          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.

                      Sistemas Operativos (IS11) – Tema 1                        94
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;
        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 tamaño 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*/
       }


                     Sistemas Operativos (IS11) – Tema 1                      95




Llamadas al Sistema en UNIX.

 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 fichero
    de tamaño 512 bytes
    permiso de lectura para propietario
    permiso de escritura para propietario
    permiso de ejecución para el grupo
    se modificó en Tue Nov 9 18:26:38 2001

                     Sistemas Operativos (IS11) – Tema 1                      96
 Llamadas al Sistema en UNIX.
#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 tamaño %d \n”, campo.st_size);
      /*PERMISOS PROPIETARIO*/
      if (((S_IRUSR)&(campo.st_mode))= =(S_IRUSR))             /*0000400*/
      printf(“De lectura para el propietario\n”);
      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”);

                         Sistemas Operativos (IS11) – Tema 1                 97




 Llamadas al Sistema en UNIX.
     /*PERMISOS GRUPO*/
     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 OTROS*/
     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”);

     printf(“Se modifico en: %s \n”, ctime(&campo.st_mtime));
     }
 }
                         Sistemas Operativos (IS11) – Tema 1                 98

								
To top