Diferencia entre revisiones de «Llamadas al sistema»

De Wiki de Sistemas Operativos
Saltar a: navegación, buscar
(El dispatcher)
 
(No se muestran 70 ediciones intermedias de 30 usuarios)
Línea 1: Línea 1:
Las llamadas al sistema son el conjunto de instrucciones de medio-bajo nivel pertenecientes al sistema operativo que proveen a los programas de recursos y funciones de software y hardware que generalmente necesitan de una gestión especial por ser recursos compartidos por otros programas y procesos.
+
= 2.7. Llamadas al sistema =
  
=Compatibilidad hacia atrás y hacia delante=
+
== Definición de llamada al sistema ==
  
En un sistema operativo bien diseñado la interfaz de las llamadas al sistema han de ser ser estables a lo largo del tiempo, de forma que la modificación funcionamiento interno de no repercuta en el funcionamiento externo de estás para asegurar la compatibilidad hacia atrás([http://en.wikipedia.org/wiki/Backward_compatibility Backward compatibility]). Además, aquellas llamadas que queden obsoletas o en desuso han de ser conservadas para, de la misma manera, asegurar el funcionamiento de programas antiguos ([http://en.wikipedia.org/wiki/Legacy_system?=Legacy_support Legacy Support]).
+
Una llamada al sistema es un método o función que puede invocar un proceso para solicitar un cierto servicio al sistema operativo. Dado que el acceso a ciertos recursos del sistema requiere la ejecución de código en modo privilegiado, el sistema operativo ofrece un conjunto de métodos o funciones que el programa puede emplear para acceder a dichos recursos. En otras palabras, el sistema operativo actúa como intermediario, ofreciendo una interfaz de programación (API) que el programa puede usar en cualquier momento para solicitar recursos gestionados por el sistema operativo.
  
En ocasiones los sistemas operativos pueden incluir en su diseño criterios de compatibilidad hacia adelante([http://en.wikipedia.org/wiki/Forward_compatibility Fordward compatibility]). Un ejemplo de este tipo de sistemas son aquellos capaces de mostrar información detallada al usuario de aquello que no pueden comprender o los sistemas ignorantes, que son aquellos que solo ejecutan lo que pueden comprender y obvian el resto.
+
Algunos ejemplos de llamadas al sistema son las siguientes:
 +
 
 +
* '''write''', que se emplea para escribir un dato en un cierto dispositivo de salida, tales como una pantalla o un disco magnético.
 +
* '''read''', que es usada para leer de un dispositivo de entrada, tales como un teclado o un disco magnético.
 +
* '''open''', que es usada para obtener un descriptor de un fichero del sistema, ese fichero suele pasarse a write.
 +
* '''close''', que se emplea para cerrar un descriptor de fichero.
 +
 
 +
Todo sistema operativo ofrece un conjunto de llamadas al sistema. En el caso de Linux 3.0, se ofrecen un total de [http://syscalls.kernelgrok.com/ 345 llamadas al sistema]. El sistema operativo xv6 ofrece también una lista de llamadas al sistema [https://github.com/mit-pdos/xv6-public/blob/master/syscall.c#L107 mucho menor] al ser un sistema operativo muy sencillo.
 +
 
 +
Toda llamada al sistema se identifica de manera unívoca mediante un valor numérico que no debe ser modificado a lo largo de la vida del sistema operativo para evitar que se rompa la compatibilidad hacia atrás.
 +
 
 +
El siguiente ejemplo muestra en C la invocación de las llamadas al sistema '''write''', '''read''', '''open''' y '''close'''.
 +
 
 +
<source lang="c">
 +
#include <stdio.h>
 +
#include <stdlib.h>
 +
 
 +
int main(void)
 +
{
 +
char buf[1024];
 +
int fd, ret;
 +
 
 +
fd = open("f123", O_RDONLY);
 +
if (fd < 0) {
 +
perror("open");
 +
exit(EXIT_FAILURE);
 +
}
 +
 
 +
ret = read(fd, buf, sizeof(buf));
 +
if (ret < 0) {
 +
perror("read");
 +
exit(EXIT_FAILURE);
 +
}
 +
close(fd);
 +
 
 +
write(1, buf, ret);
 +
}
 +
 
 +
</source>
 +
 
 +
=== Familias de llamadas al sistema operativo: POSIX y WIN32/64 ===
 +
 
 +
Las dos familias de APIs estandarizas más importantes son:
 +
 
 +
* [http://es.wikipedia.org/wiki/POSIX POSIX].
 +
* WIN32/64, empleada en los sistemas operativos de tipo-Windows. Además, existen emuladores como '''Wine''' ''(permite instalar y ejecutar aplicaciones de Windows en distribuciones de Linux)'' que también las implementan.
 +
 
 +
== Implementación de llamadas al sistema ==
 +
 
 +
El siguiente ejemplo muestra el código en ensamblador de x86 para invocar a la llamada al sistema '''write''' que permite escribir un dato en cualquier dispositivo. En concreto, se va a escribir una cadena por el dispositivo de salida '''pantalla''', que se identifica mediante el descriptor de fichero número 1.
 +
 
 +
<source lang="asm">
 +
section .text
 +
    global _start
 +
_start:
 +
    mov eax, 4        ;cargamos el número de la llamada al sistema en el regitro eax
 +
    mov ebx, 1        ;cargamos el descriptor de fichero sobre el que queremos escribir
 +
    mov ecx, string    ;cargamos en ecx la dirección de la cadena a imprimir
 +
    mov edx, length  ;cargamos en edx el tamaño de la cadena a imprimir
 +
    int 80h            ;se invoca a interrupción por software número 80
 +
                      ;que invoca al dispatcher de llamadas al sistema
 +
 
 +
    mov eax, 1
 +
    mov ebx, 0
 +
    int 80h
 +
 
 +
section .data
 +
    string: db "Hola Mundo", 0x0A
 +
    lenght: equ 13
 +
</source>
 +
 
 +
La instrucción ''int'' forma parte del conjunto de instrucciones de procesadores x86. Esta instrucción emite una [[Gestión_de_Entrada/Salida|interrupción]] por software cuyo tratamiento es realizado por la rutina ''dispatcher''. Dicha rutina se encarga del tratamiento de la interrupción por software número 80.
 +
 
 +
En el siguiente segmento de código se muestra una llamada a sistema en un procesador de 32 bits:
 +
<syntaxhighlight lang="asm">
 +
_start:
 +
    movl $4, %eax  ; use the write syscall
 +
    movl $1, %ebx  ; write to stdout
 +
    movl $msg, %ecx ; use string "Hello World"
 +
    movl $12, %edx  ; write 12 characters
 +
    int $0x80      ; make syscall
 +
   
 +
    movl $1, %eax  ; use the _exit syscall
 +
    movl $0, %ebx  ; error code 0
 +
    int $0x80      ; make syscall
 +
</syntaxhighlight>
 +
 
 +
Análogamente en un procesador de 64 bits:
 +
<syntaxhighlight lang="asm">
 +
_start:
 +
    movq $4, %rax  ; use the write syscall
 +
    movq $1, %rdi  ; write to stdout
 +
    movq $msg, %rsi ; use string "Hello World"
 +
    movq $12, %rdx  ; write 12 characters
 +
    syscall        ; make syscall
 +
   
 +
    movq $60, %rax  ; use the _exit syscall
 +
    movq $0, %rdi  ; error code 0
 +
    syscall        ; make syscall
 +
</syntaxhighlight>
 +
 
 +
'''Ejemplo de llamadas al sistema de Linux (64 bits):''' http://blog.rchapman.org/posts/Linux_System_Call_Table_for_x86_64/
 +
 
 +
[http://cs.lmu.edu/~ray/notes/linuxsyscalls/ Implementación de llamadas al sistema en Linux (32 y 64 bit)]
 +
 
 +
== El ''dispatcher'' ==
 +
 
 +
El dispatcher, que forma parte del núcleo del SO, se ejecuta cuando se invoca una llamada al sistema.
 +
Cuando un proceso hace una llamada al sistema, el dispatcher, se encarga de invocar la llamada que el proceso ha solicitado.
 +
 +
Tiene un comportamiento sincronizado, cuando recibe una llamada se la pasa al sistema operativo y hasta que no recibe respuesta no atiende otra llamada.
 +
 
 +
En el caso de x86, el dispatcher consulta el registro eax e invoca a la llamada al sistema identificada con dicha numeración.
 +
 
 +
El sistema xv6 ofrece un dispatcher muy sencillo, que se puede consultar [https://github.com/mit-pdos/xv6-public/blob/master/syscall.c#L132 aquí].
 +
 
 +
2.8. [[Ejercicios_fundamentos_Sistemas_Operativos | Ejercicios]]
 +
 
 +
3.1. [[Modelos_de_Diseño_de_Sistemas_Operativos | Modelos de Diseño de SSOO]]

Revisión actual del 17:00 19 feb 2019

2.7. Llamadas al sistema

Definición de llamada al sistema

Una llamada al sistema es un método o función que puede invocar un proceso para solicitar un cierto servicio al sistema operativo. Dado que el acceso a ciertos recursos del sistema requiere la ejecución de código en modo privilegiado, el sistema operativo ofrece un conjunto de métodos o funciones que el programa puede emplear para acceder a dichos recursos. En otras palabras, el sistema operativo actúa como intermediario, ofreciendo una interfaz de programación (API) que el programa puede usar en cualquier momento para solicitar recursos gestionados por el sistema operativo.

Algunos ejemplos de llamadas al sistema son las siguientes:

  • write, que se emplea para escribir un dato en un cierto dispositivo de salida, tales como una pantalla o un disco magnético.
  • read, que es usada para leer de un dispositivo de entrada, tales como un teclado o un disco magnético.
  • open, que es usada para obtener un descriptor de un fichero del sistema, ese fichero suele pasarse a write.
  • close, que se emplea para cerrar un descriptor de fichero.

Todo sistema operativo ofrece un conjunto de llamadas al sistema. En el caso de Linux 3.0, se ofrecen un total de 345 llamadas al sistema. El sistema operativo xv6 ofrece también una lista de llamadas al sistema mucho menor al ser un sistema operativo muy sencillo.

Toda llamada al sistema se identifica de manera unívoca mediante un valor numérico que no debe ser modificado a lo largo de la vida del sistema operativo para evitar que se rompa la compatibilidad hacia atrás.

El siguiente ejemplo muestra en C la invocación de las llamadas al sistema write, read, open y close.

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
	char buf[1024];
	int fd, ret;

	fd = open("f123", O_RDONLY);
	if (fd < 0) {
		perror("open");
		exit(EXIT_FAILURE);
	}

	ret = read(fd, buf, sizeof(buf));
	if (ret < 0) {
		perror("read");
		exit(EXIT_FAILURE);
	}
	close(fd);

	write(1, buf, ret);
}

Familias de llamadas al sistema operativo: POSIX y WIN32/64

Las dos familias de APIs estandarizas más importantes son:

  • POSIX.
  • WIN32/64, empleada en los sistemas operativos de tipo-Windows. Además, existen emuladores como Wine (permite instalar y ejecutar aplicaciones de Windows en distribuciones de Linux) que también las implementan.

Implementación de llamadas al sistema

El siguiente ejemplo muestra el código en ensamblador de x86 para invocar a la llamada al sistema write que permite escribir un dato en cualquier dispositivo. En concreto, se va a escribir una cadena por el dispositivo de salida pantalla, que se identifica mediante el descriptor de fichero número 1.

section .text
    global _start
_start:
    mov eax, 4         ;cargamos el número de la llamada al sistema en el regitro eax
    mov ebx, 1         ;cargamos el descriptor de fichero sobre el que queremos escribir
    mov ecx, string    ;cargamos en ecx la dirección de la cadena a imprimir
    mov edx, length   ;cargamos en edx el tamaño de la cadena a imprimir
    int 80h            ;se invoca a interrupción por software número 80
                       ;que invoca al dispatcher de llamadas al sistema

    mov eax, 1
    mov ebx, 0
    int 80h

section .data
    string: db "Hola Mundo", 0x0A
    lenght: equ 13

La instrucción int forma parte del conjunto de instrucciones de procesadores x86. Esta instrucción emite una interrupción por software cuyo tratamiento es realizado por la rutina dispatcher. Dicha rutina se encarga del tratamiento de la interrupción por software número 80.

En el siguiente segmento de código se muestra una llamada a sistema en un procesador de 32 bits:

_start:
    movl $4, %eax   ; use the write syscall
    movl $1, %ebx   ; write to stdout
    movl $msg, %ecx ; use string "Hello World"
    movl $12, %edx  ; write 12 characters
    int $0x80       ; make syscall
    
    movl $1, %eax   ; use the _exit syscall
    movl $0, %ebx   ; error code 0
    int $0x80       ; make syscall

Análogamente en un procesador de 64 bits:

_start:
    movq $4, %rax   ; use the write syscall
    movq $1, %rdi   ; write to stdout
    movq $msg, %rsi ; use string "Hello World"
    movq $12, %rdx  ; write 12 characters
    syscall         ; make syscall
    
    movq $60, %rax  ; use the _exit syscall
    movq $0, %rdi   ; error code 0
    syscall         ; make syscall

Ejemplo de llamadas al sistema de Linux (64 bits): http://blog.rchapman.org/posts/Linux_System_Call_Table_for_x86_64/

Implementación de llamadas al sistema en Linux (32 y 64 bit)

El dispatcher

El dispatcher, que forma parte del núcleo del SO, se ejecuta cuando se invoca una llamada al sistema. Cuando un proceso hace una llamada al sistema, el dispatcher, se encarga de invocar la llamada que el proceso ha solicitado.

Tiene un comportamiento sincronizado, cuando recibe una llamada se la pasa al sistema operativo y hasta que no recibe respuesta no atiende otra llamada.

En el caso de x86, el dispatcher consulta el registro eax e invoca a la llamada al sistema identificada con dicha numeración.

El sistema xv6 ofrece un dispatcher muy sencillo, que se puede consultar aquí.

2.8. Ejercicios

3.1. Modelos de Diseño de SSOO