Llamadas al sistema de entrada-salida en C | Crear, Abrir, Cerrar, Leer, Escribir

Terminología importante

¿Qué es el descriptor de archivo?
El descriptor de archivo es un número entero que identifica de forma única un archivo abierto del proceso.

Tabla de descriptores de archivos: la tabla de descriptores de archivos es la colección de índices de array de enteros que son descriptores de archivos en los que los elementos son punteros a las entradas de la tabla de archivos. Se proporciona una tabla de descriptores de archivo única en el sistema operativo para cada proceso.

Entrada de la tabla de archivos: las entradas de la tabla de archivos son una estructura sustituta en memoria para un archivo abierto, que se crea cuando se procesa una solicitud para abrir un archivo y estas entradas mantienen la posición del archivo.

Descriptores de archivo estándar : cuando se inicia cualquier proceso, el fd (descriptor de archivo) 0, 1, 2 de la tabla de descriptores de archivos de proceso se abre automáticamente (de manera predeterminada), cada uno de estos 3 fd hace referencia a la entrada de la tabla de archivos para un archivo llamado /dev/tty

/dev/tty : Suplente en memoria para el terminal
Terminal : Combinación de teclado/pantalla de video
 

Leer desde stdin => leer desde fd 0 : cada vez que escribimos cualquier carácter desde el teclado, se lee desde stdin hasta fd 0 y se guarda en un archivo llamado /dev/tty.
Write to stdout => write to fd 1 : Cada vez que vemos una salida en la pantalla de video, es del archivo llamado /dev/tty y escrito en stdout en pantalla a través de fd 1.
Write to stderr => write to fd 2 : We ver cualquier error en la pantalla de video, también es desde ese archivo escribir en stderr en pantalla a través de fd 2.

Llamadas del sistema de E/S

Básicamente, hay un total de 5 tipos de llamadas al sistema de E/S:

1. Crear: se usa para crear un nuevo archivo vacío.

Syntax in C language: 
int create(char *filename, mode_t mode)

Parámetro:

  • filename : nombre del archivo que desea crear
  • modo: indica los permisos del nuevo archivo.

Devoluciones:

  • devuelve el primer descriptor de archivo no utilizado (generalmente 3 cuando se crea por primera vez en proceso porque 0, 1, 2 fd están reservados)
  • devuelve -1 cuando hay error

Cómo funciona en el sistema operativo

  • Crear nuevo archivo vacío en el disco
  • Crear entrada de tabla de archivos
  • Establezca el primer descriptor de archivo no utilizado para que apunte a la entrada de la tabla de archivos
  • Se utiliza el descriptor de archivo de retorno, -1 en caso de error

2. abrir : se usa para abrir el archivo para leerlo, escribirlo o ambos.

Syntax in C language 
#include<sys/types.h>
#include<sys/stat.h>
#include <fcntl.h>  
int open (const char* Path, int flags [, int mode ]); 

Parámetros

  • Ruta: ruta al archivo que desea utilizar 
    • use la ruta absoluta que comience con «/», cuando no esté trabajando en el mismo directorio de archivo.
    • Use la ruta relativa que es solo el nombre del archivo con la extensión, cuando esté trabajando en el mismo directorio del archivo.
  • banderas: cómo te gusta usar
    • O_RDONLY : solo lectura, O_WRONLY : solo escritura, O_RDWR : lectura y escritura, O_CREAT : crear archivo si no existe, O_EXCL : impedir la creación si ya existe

Cómo funciona en el sistema operativo

  • Encuentra el archivo existente en el disco
  • Crear entrada de tabla de archivos
  • Establezca el primer descriptor de archivo no utilizado para que apunte a la entrada de la tabla de archivos
  • Se utiliza el descriptor de archivo de retorno, -1 en caso de error

C

// C program to illustrate 
// open system call 
#include<stdio.h> 
#include<fcntl.h> 
#include<errno.h> 
extern int errno; 
int main() 
{     
    // if file does not have in directory 
    // then file foo.txt is created. 
    int fd = open("foo.txt", O_RDONLY | O_CREAT); 
      
    printf("fd = %d/n", fd); 
      
    if (fd ==-1) 
    { 
        // print which type of error have in a code 
        printf("Error Number % d\n", errno); 
          
        // print program detail "Success or failure" 
        perror("Program");                 
    } 
    return 0; 
} 

Producción:

fd = 3

3. cerrar: le dice al sistema operativo que ha terminado con un descriptor de archivo y cierra el archivo señalado por fd. 

Syntax in C language
#include <fcntl.h>
int close(int fd); 

Parámetro:

  • fd : descriptor de archivo

Devolver:

  • 0 en éxito.
  • -1 en error.

Cómo funciona en el sistema operativo

  • Destruya la entrada de la tabla de archivos a la que hace referencia el elemento fd de la tabla de descriptores de archivos
    , ¡siempre y cuando ningún otro proceso lo apunte!
  • Establezca el elemento fd de la tabla de descriptores de archivo en NULL

C

// C program to illustrate close system Call 
#include<stdio.h> 
#include <fcntl.h> 
int main() 
{ 
    int fd1 = open("foo.txt", O_RDONLY); 
    if (fd1 < 0) 
    { 
        perror("c1"); 
        exit(1); 
    } 
    printf("opened the fd = % d\n", fd1); 
      
    // Using close system Call 
    if (close(fd1) < 0) 
    { 
        perror("c1"); 
        exit(1); 
    } 
    printf("closed the fd.\n"); 
} 

Producción:

opened the fd = 3
closed the fd.

C

// C program to illustrate close system Call 
#include<stdio.h> 
#include<fcntl.h> 
int main() 
{ 
    // assume that foo.txt is already created 
    int fd1 = open("foo.txt", O_RDONLY, 0); 
    close(fd1); 
      
    // assume that baz.tzt is already created 
    int fd2 = open("baz.txt", O_RDONLY, 0); 
      
    printf("fd2 = % d\n", fd2); 
    exit(0); 
} 

Producción:

fd2 = 3

Aquí, en este código, primero open() devuelve 3 porque cuando se crea el proceso principal, stdin , stdout y stderr ya toman fd 0, 1, 2 . Entonces, el primer descriptor de archivo no utilizado es 3 en la tabla de descriptores de archivo. Después de eso, en close() la llamada al sistema es gratuita, este descriptor de 3 archivos y luego establece el descriptor de 3 archivos como nulo . Entonces, cuando llamamos a second open(), entonces el primer fd no utilizado también es 3 . Entonces, la salida de este programa es 3 .

4. leer: del archivo indicado por el descriptor de archivo fd, la función read() lee cnt bytes de entrada en el área de memoria indicada por buf. Una lectura() exitosa actualiza el tiempo de acceso al archivo.

Syntax in C language 
size_t read (int fd, void* buf, size_t cnt);  

Parámetros:

  • fd: descriptor de archivo
  • buf: búfer para leer datos
  • cnt: longitud del búfer

Devoluciones: cuántos bytes se leyeron realmente

  • return Número de bytes leídos en caso de éxito
  • devuelve 0 al llegar al final del archivo
  • devolver -1 en caso de error
  • devuelve -1 en interrupción de señal

Puntos importantes

  • buf necesita apuntar a una ubicación de memoria válida con una longitud no menor que el tamaño especificado debido al desbordamiento.
  • fd debe ser un descriptor de archivo válido devuelto por open() para realizar la operación de lectura porque si fd es NULL, la lectura debería generar un error.
  • cnt es el número solicitado de bytes leídos, mientras que el valor devuelto es el número real de bytes leídos. Además, algunas veces la llamada al sistema de lectura debería leer menos bytes que cnt.

C

// C program to illustrate 
// read system Call 
#include<stdio.h> 
#include <fcntl.h> 
int main() 
{ 
int fd, sz; 
char *c = (char *) calloc(100, sizeof(char)); 
  
fd = open("foo.txt", O_RDONLY); 
if (fd < 0) { perror("r1"); exit(1); } 
  
sz = read(fd, c, 10); 
printf("called read(% d, c, 10). returned that"
        " %d bytes were read.\n", fd, sz); 
c[sz] = '\0'; 
printf("Those bytes are as follows: % s\n", c); 
} 

Producción:

called read(3, c, 10).  returned that 10 bytes  were read.
Those bytes are as follows: 0 0 0 foo.

Suponga que foobar.txt consiste en los 6 caracteres ASCII “foobar”. Entonces, ¿cuál es la salida del siguiente programa?

C

// C program to illustrate 
// read system Call 
#include<stdio.h> 
#include<unistd.h> 
#include<fcntl.h> 
#include<stdlib.h> 
  
int main() 
{ 
    char c; 
    int fd1 = open("sample.txt", O_RDONLY, 0); 
    int fd2 = open("sample.txt", O_RDONLY, 0); 
    read(fd1, &c, 1); 
    read(fd2, &c, 1); 
    printf("c = %c\n", c); 
    exit(0); 
} 

Producción:

c = f

Los descriptores fd1 y fd2 tienen cada uno su propia entrada en la tabla de archivos abiertos, por lo que cada descriptor tiene su propia posición de archivo para foobar.txt . Por lo tanto, la lectura de fd2 lee el primer byte de foobar.txt y la salida es c = f , no c = o .

5. escribir: escribe cnt bytes desde buf al archivo o socket asociado con fd. cnt no debe ser mayor que INT_MAX (definido en el archivo de encabezado limits.h). Si cnt es cero, write() simplemente devuelve 0 sin intentar ninguna otra acción.

#include <fcntl.h>
size_t write (int fd, void* buf, size_t cnt); 

Parámetros:

  • fd: descriptor de archivo
  • buf: búfer para escribir datos
  • cnt: longitud del búfer

Devoluciones: cuántos bytes se escribieron realmente

  • return Número de bytes escritos en caso de éxito
  • devuelve 0 al llegar al final del archivo
  • devolver -1 en caso de error
  • devuelve -1 en interrupción de señal

Puntos importantes

  • El archivo debe abrirse para las operaciones de escritura.
  • buf debe tener al menos la longitud especificada por cnt porque si el tamaño de buf es menor que cnt, entonces buf conducirá a la condición de desbordamiento.
  • cnt es el número solicitado de bytes para escribir, mientras que el valor devuelto es el número real de bytes escritos. Esto sucede cuando fd tiene menos bytes para escribir que cnt.
  • Si write() es interrumpido por una señal, el efecto es uno de los siguientes:
    -Si write() aún no ha escrito ningún dato, devuelve -1 y establece errno en EINTR.
    -Si write() ha escrito con éxito algunos datos, devuelve la cantidad de bytes que escribió antes de que se interrumpiera.

C

// C program to illustrate 
// write system Call 
#include<stdio.h> 
#include <fcntl.h> 
main() 
{ 
int sz; 
  
int fd = open("foo.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644); 
if (fd < 0) 
{ 
    perror("r1"); 
    exit(1); 
} 
  
sz = write(fd, "hello geeks\n", strlen("hello geeks\n")); 
  
printf("called write(% d, \"hello geeks\\n\", %d)."
    " It returned %d\n", fd, strlen("hello geeks\n"), sz); 
  
close(fd); 
} 

Producción:

called write(3, "hello geeks\n", 12).  it returned 11

Aquí, cuando ves en el archivo foo.txt después de ejecutar el código, obtienes un » hola geeks «. Si el archivo foo.txt ya tiene algún contenido, escriba la llamada al sistema sobrescriba el contenido y todo el contenido anterior se eliminará y solo el contenido » hola geeks » tendrá en el archivo.

Imprime “hola mundo” desde el programa sin usar ninguna función printf o cout.

C

// C program to illustrate 
// I/O system Calls 
#include<stdio.h> 
#include<string.h> 
#include<unistd.h> 
#include<fcntl.h> 
  
int main (void) 
{ 
    int fd[2]; 
    char buf1[12] = "hello world"; 
    char buf2[12]; 
  
    // assume foobar.txt is already created 
    fd[0] = open("foobar.txt", O_RDWR);         
    fd[1] = open("foobar.txt", O_RDWR); 
      
    write(fd[0], buf1, strlen(buf1));         
    write(1, buf2, read(fd[1], buf2, 12)); 
  
    close(fd[0]); 
    close(fd[1]); 
  
    return 0; 
} 

Producción:

hello world

En este código, la string «hello world» de la array buf1 se escribe primero en stdin fd[0] y luego esta string se escribe en stdin en la array buf2. Después de eso, escriba en la array buf2 a la salida estándar e imprima la salida » hola mundo «.
Este artículo es una contribución de Kadam Patel . Si te gusta GeeksforGeeks y te gustaría contribuir, también puedes escribir un artículo usando write.geeksforgeeks.org o enviar tu artículo por correo a review-team@geeksforgeeks.org. Vea su artículo que aparece en la página principal de GeeksforGeeks y ayude a otros Geeks.
Escriba comentarios si encuentra algo incorrecto o si desea compartir más información sobre el tema tratado anteriormente.
 

Publicación traducida automáticamente

Artículo escrito por GeeksforGeeks-1 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *