Las llamadas al sistema son las llamadas que realiza un programa al núcleo del sistema para proporcionar los servicios a los que el programa no tiene acceso directo. Por ejemplo, proporcionar acceso a dispositivos de entrada y salida, como monitores y teclados. Podemos utilizar varias funciones proporcionadas en el lenguaje de programación C para llamadas al sistema de entrada/salida, como crear, abrir, leer, escribir, etc.
Antes de pasar a las llamadas al sistema de E/S, necesitamos conocer algunos términos importantes.
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: un archivo La tabla de descriptores es la colección de índices de matriz de enteros que son descriptores de archivos en los que los elementos son punteros a las entradas de la tabla de archivos. En el sistema operativo se proporciona una tabla de descriptores de archivos única para cada proceso.
Entrada de tabla de archivos: Las entradas de la tabla de archivos son una estructura sustituta en memoria para un archivo abierto, que se crea al procesar una solicitud para abrir el archivo y estas entradas mantienen la posición del archivo.

Descriptores de archivos estándar : Cuando se inicia cualquier proceso, el fd (descriptor de archivo) 0, 1, 2 de la tabla de descriptores de archivos de ese proceso se abre automáticamente (de forma predeterminada) cada una de estas 3 fd hace referencia a la entrada de la tabla de archivos para un archivo llamado /desarrollo/tty
/desarrollo/tty : sustituto en memoria del terminal.
Terminal : Combinación de teclado/pantalla de vídeo.

Leer desde stdin => leer desde fd 0 : Cada vez que escribimos un carácter desde el teclado, se lee desde stdin hasta fd 0 y se guarda en un archivo llamado /dev/tty.
Escribir en stdout => escribir en fd 1 : Siempre que vemos alguna salida en la pantalla de video, es del archivo llamado /dev/tty y escrito en la salida estándar en la pantalla hasta fd 1.
Escribir en stderr => escribir en fd 2 : Vemos cualquier error en la pantalla de video, también es desde ese archivo que se escribe en stderr en la pantalla a través de fd 2.
Llamadas al sistema de entrada/salida
Básicamente, existen un total de 5 tipos de llamadas al sistema de E/S:
1. C crear
La función create() se usa para crear un nuevo archivo vacío en C. Podemos especificar el permiso y el nombre del archivo que queremos crear usando la función create(). esta definido por dentro archivo de encabezado y las banderas que se pasan como argumentos se definen dentro archivo de cabecera.
Sintaxis de crear() en C
int create (char * filename , mode_t mode );>
Parámetro
- Nombre del archivo: nombre del archivo que desea crear
- modo: indica los permisos del nuevo archivo.
Valor de retorno
- devolver el primer descriptor de archivo no utilizado (generalmente 3 cuando se crea el uso por primera vez en el proceso porque 0, 1, 2 fd están reservados)
- devolver -1 cuando hay un error
Cómo funciona C create() en el sistema operativo
- Cree un nuevo archivo vacío en el disco.
- Crear entrada de tabla de archivos.
- Configure el primer descriptor de archivo no utilizado para que apunte a la entrada de la tabla de archivos.
- Descriptor de archivo de retorno utilizado, -1 en caso de error.
2.C abierto
La función open() en C se utiliza para abrir el archivo para lectura, escritura o ambas cosas. También es capaz de crear el archivo si no existe. esta definido por dentro archivo de encabezado y las banderas que se pasan como argumentos se definen dentro archivo de cabecera.
Sintaxis de open() en C
int open (const char* Path , int flags );>
Parámetros
- Camino: Ruta al archivo que queremos abrir.
- Utilizar el camino absoluto comenzando con / cuando estás no trabajando en el mismo directorio como el archivo fuente C.
- Usar camino relativo que es solo el nombre del archivo con extensión, cuando estás trabajando en el mismo directorio como el archivo fuente C.
- banderas: Se utiliza para especificar cómo desea abrir el archivo. Podemos utilizar las siguientes banderas.
| Banderas | Descripción |
|---|---|
| O_RDONLY | Abre el archivo en modo de solo lectura. |
| O_WRONLY | Abre el archivo en modo de solo escritura. |
| O_RDWR | Abre el archivo en modo lectura y escritura. |
| O_CREAR | Crea un archivo si no existe. |
| O_EXCL | Impedir la creación si ya existe. |
| O_ ANEXAR | Abre el archivo y coloca el cursor al final del contenido. |
| O_ASYNC | Habilita el control de entrada y salida por señal. |
| O_CLOEXEC | Habilite el modo de cierre en ejecución en el archivo abierto. |
| O_NONBLOCK | Desactiva el bloqueo del archivo abierto. |
| O_TMPFILE | Cree un archivo temporal sin nombre en la ruta especificada. |
Cómo funciona C open() en el sistema operativo
- Busque el archivo existente en el disco.
- Crear entrada de tabla de archivos.
- Configure el primer descriptor de archivo no utilizado para que apunte a la entrada de la tabla de archivos.
- Descriptor de archivo de retorno utilizado, -1 en caso de error.
Ejemplo de C abierto()
C
// C program to illustrate> // open system call> #include> #include> #include> #include> 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
'>, fd);> >if> (fd == -1) {> >// print which type of error have in a code> >printf>(>'Error Number % d
'>,>errno>);> >// print program detail 'Success or failure'> >perror>(>'Program'>);> >}> >return> 0;> }> |
>
>
Producción
fd = 3>
3. C cerrar
La función close() en C le dice al sistema operativo que ha terminado con un descriptor de archivo y cierra el archivo señalado por el descriptor de archivo. esta definido por dentro archivo de cabecera.
Sintaxis de close() en C
int close(int fd);>
Parámetro
- fd:F descriptor del archivo que desea cerrar.
Valor de retorno
- 0 sobre el éxito.
- -1 por error.
Cómo funciona C close() en el sistema operativo
- Destruir 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 archivos en NULO
Ejemplo 1: cerrar() en C
C
// C program to illustrate close system Call> #include> #include> #include> int> main()> {> >int> fd1 = open(>'foo.txt'>, O_RDONLY);> >if> (fd1 <0) {> >perror>(>'c1'>);> >exit>(1);> >}> >printf>(>'opened the fd = % d
'>, fd1);> >// Using close system Call> >if> (close(fd1) <0) {> >perror>(>'c1'>);> >exit>(1);> >}> >printf>(>'closed the fd.
'>);> }> |
>
>
Producción
opened the fd = 3 closed the fd.>
Ejemplo 2:
C
sistema operativo de red
// C program to illustrate close system Call> #include> #include> 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
'>, fd2);> >exit>(0);> }> |
>
>
Producción
fd2 = 3>
Aquí, en este código, primero se devuelve open() 3 porque cuando se crea el proceso principal, entonces fd 0, 1, 2 ya están tomados por entrada estándar , salida estándar, y stderr . Entonces, el primer descriptor de archivo no utilizado es 3 en la tabla de descriptores de archivos. Después de eso, en close() la llamada al sistema es gratuita. 3 descriptores de archivos y luego configurar 3 descriptores de archivos como nulo . Entonces, cuando llamamos al segundo open(), el primer fd no utilizado también es 3 . Entonces, el resultado de este programa es 3 .
4. C leer
Del archivo indicado por el descriptor de archivo fd, la función read() lee la cantidad especificada de bytes cnt de entrada en el área de memoria indicada por buf . Una lectura exitosa() actualiza el tiempo de acceso al archivo. La función read() también se define dentro del archivo de encabezado.
Sintaxis de lectura() en C
size_t read (int fd , void* buf , size_t cnt );>
Parámetros
- fd: descriptor de archivo del archivo desde el cual se leerán los datos.
- buf: buffer para leer datos de
- ct: longitud del buffer
Valor de retorno
- devolver Número de bytes leídos en caso de éxito
- devolver 0 al llegar al final del archivo
- devolver -1 en caso de error
- retorno -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 desde open() para realizar la operación de lectura porque si fd es NULL entonces la lectura debería generar un error.
- cnt es el número solicitado de bytes leídos, mientras que el valor de retorno 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.
Ejemplo de lectura() en C
C
// C program to illustrate> // read system Call> #include> #include> #include> 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.
'>,> >fd, sz);> >c[sz] =>' '>;> >printf>(>'Those bytes are as follows: % s
'>, c);> >return> 0;> }> |
>
>
Producción
called read(3, c, 10). returned that 10 bytes were read. Those bytes are as follows: 0 0 0 foo.>
Supongamos que foobar.txt consta de foobar de 6 caracteres ASCII. Entonces ¿cuál es el resultado del siguiente programa?
C
// C program to illustrate> // read system Call> #include> #include> #include> #include> 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
'>, c);> >exit>(0);> }> |
>
>
Producción
c = f>
Los descriptores fd1 y fd2 cada uno tiene su propia entrada en la tabla de archivos abiertos, por lo que cada descriptor tiene su propia posición de archivo para foobar.txt . Así, la lectura de fd2 lee el primer byte de foobar.txt , y la salida es c = f , no c = o .
5. C 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.
La escritura() también está definida dentro archivo de cabecera.
Sintaxis de escribir() en C
size_t write (int fd , void* buf , size_t cnt );>
Parámetros
- fd: descriptor de archivo
- buf: buffer para escribir datos.
- ct: longitud del buffer.
Valor de retorno
- devuelve el número de bytes escritos en caso de éxito.
- devuelve 0 al llegar al final del archivo.
- devuelve -1 en caso de error.
- devuelve -1 en caso de interrupciones de señal.
Puntos importantes sobre la escritura en C
- El archivo debe abrirse para operaciones de escritura.
- buf debe ser al menos tan largo como lo especifica cnt porque si el tamaño de buf es menor que cnt, entonces buf provocará la condición de desbordamiento.
- cnt es el número solicitado de bytes para escribir, mientras que el valor de retorno 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 el número de bytes que escribió antes de ser interrumpido.
Ejemplo de escritura() en C
C
// C program to illustrate> // write system Call> #include> #include> 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
'>,>strlen>(>'hello geeks
'>));> printf>(>'called write(% d, 'hello geeks
', %d).'> >' It returned %d
'>, fd,>strlen>(>'hello geeks
'>), sz);> close(fd);> }> |
índice de cadena java de
>
>
Producción
called write(3, 'hello geeks ', 12). it returned 11>
Aquí, cuando ve el archivo foo.txt después de ejecutar el código, obtiene un hola frikis . Si el archivo foo.txt ya tiene contenido, las llamadas del sistema de escritura sobrescriben el contenido y todo el contenido anterior se elimina. eliminado y solo hola frikis contenido tendrá en el archivo.
Ejemplo: imprima hola mundo desde el programa sin utilizar ninguna función printf.
C
// C program to illustrate> // I/O system Calls> #include> #include> #include> #include> 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 cadena de la matriz buf1 Hola Mundo se escribe primero en stdin fd[0] y luego esta cadena se escribe en stdin en la matriz buf2. Después de eso, escriba en la matriz buf2 en la salida estándar e imprima la salida. Hola Mundo .