SISTEMAS OPERATIVOS:
Lección2:
Servicios de los Sistemas Operativos
1
Contenidos
• Llamadas al sistema
• Servicios para procesos
• Servicios para archivos y directorios
2
Ejecución Sistema Operativo
• Una vez finalizado el arranque, el sistema operativo
solamente se ejecuta en respuesta a interrupciones.
• El sistema operativo se activa cuando debe
responder a:
– Una petición de servicio de un proceso.
– Una interrupción (periférico o reloj).
– Excepción hardware.
3
Fases de Activación del Sistema operativo
Avanza la ejecución
Proceso A Se solicita el SO
Salva el estado del proceso A
Sistema Realiza la función pedida
operativo
Planificador
Activador
Proceso B
4
Activación de servicios
• Una invocación directa a una rutina del sistema
operativo plantea problemas de seguridad.
– ¿Cómo realizar cambios en el modo de ejecución de modo
seguro?
• Utilizando una interrupción software (trap) se consigue la
activación del sistema operativo de modo seguro.
– Rutina de biblioteca:
• Instrucciones de máquina que prepara la llamada al SO.
• Instrucción de trap.
• Instrucciones de proceso posterior de los resultados de la llamada
al sistema operativo.
5
Servicios del sistema operativo: Llamadas al sistema
• Interfaz entre aplicaciones y SO.
– Generalmente disponibles como funciones en ensamblador.
– Actualmente en otros lenguajes de alto nivel (C, C++, …).
• Servicios típicos del sistema operativo
– Gestión de procesos
– Gestión de procesos ligeros
– Gestión de señales, temporizadores
– Gestión de memoria
– Gestión de ficheros y directorios
• Ejemplos de llamada
– read: permite leer datos de un fichero
– fork: permite crear un nuevo proceso
6
Invocación de la llamada
• Cada función de la interfaz de programación (API) se
corresponde con algún servicio del sistema
operativo.
– La función es un envoltorio para el código que invoca el
servicio del sistema operativo.
• Incluye la ejecución de una instrucción de trap que
transfiere el control al sistema operativo mediante la
generación de una interrupción.
• El sistema operativo trata la interrupción y devuelve
el control al programa de usuario.
7
Invocación de la llamada
read
asm (“
lw $a0,
fd lw 1 Sistema
$a1, b lw 2 Operativo
Biblioteca $a2, lo
li $v0,
de sistema 14
syscall
sw $v0,
r” 14 - > read_syscall
);
return r;
Programa
de usuario
3
4
Código de read(fd,b,lo)
usuario
10
Selección de servicio
• Al existir una única instrucción de trap y múltiples
servicios se hace necesario establecer algún
mecanismo de paso de parámetros entre el proceso
de usuario y el núcleo.
• Como mínimo siempre se debe pasar una
especificación del servicio que se desea ejecutar.
– Típicamente un identificador numérico.
9
Paso de parámetros
• Tres métodos genéricos para pasar parámetros a las
llamadas al sistema:
– En registros.
– En una tabla de memoria, cuya dirección se pasa al SO en
un registro.
– Poner los parámetros en la pila del programa y dejar que
el SO los extraiga.
• Cada SO proporciona sus propias llamadas al
sistema:
– Estándar POSIX en UNIX y LINUX.
– Win32 en Windows NT
– Win64 en Windows 10/Windows 11.
10
Rutina de tratamiento
• La rutina de tratamiento debe:
– Recuperar los parámetros enviados por el proceso de
usuario.
– Identificar el servicio que se desea ejecutar.
– Determinar la dirección de la rutina de servicio adecuada
(indexación en una tabla de rutinas de servicio).
– Transferir el control a la rutina de servicio.
11
Invocación de llamada
int read(int fd, char * b, int lon) {
int r;
asm (“
lw $a0, fd
lw $a1, b
lw $a2, lon READ_SYSCALL
li $v0, 14
syscall TRAP
sw $v0, r”
);
return r;
}
12
Interfaz del programador
• Esta interfaz ofrece la visión que como máquina
extendida tiene el usuario del sistema operativo
• Cada sistema operativo puede ofrecer una o varias
interfaces:
– Linux: POSIX
– Windows: Win32, Win64, POSIX
13
Estándar POSIX
• Interfaz estándar de sistemas operativos de IEEE.
• Objetivo: portabilidad de las aplicaciones
entre diferentes plataformas y sistemas
operativos.
• NO es una implementación. Sólo define una interfaz
• Diferentes estándares
– 1003.1 Servicios básicos del SO
– 1003.1a Extensiones a los servicios básicos
– 1003.1b Extensiones de tiempo real
– 1003.1c Extensiones de procesos ligeros
– 1003.2 Shell y utilidades
– 1003.2b Utilidades adicionales
14
UNIX03
• Single Unix Specification UNIX 03.
• Es una evolución que engloba a POSIX y otros
estándares (X/Open XPG4, ISO C).
• Incluye no solamente la interfaz de programación,
sino también otros aspectos:
– Servicios ofrecidos.
– Intérprete de mandatos.
– Utilidades disponibles.
15
Características de POSIX
• Nombres de funciones cortos y en letras minúsculas:
– fork
– read
– close
• Las funciones normalmente devuelve 0 en caso de
éxito o –1 en caso de error.
– Variable errno.
• Recursos gestionados por el sistema operativo se
referencian mediante descriptores (números
enteros)
16
Ejemplo: Ejecución de un mandato
17
Contenidos
• Llamadas al sistema
• Servicios para procesos
• Servicios para archivos y directorios
20
Servicio fork
• pid_t fork(void);
• Duplica el proceso que invoca la llamada.
• El proceso padre y el proceso hijo siguen ejecutando el mismo
programa.
• El proceso hijo hereda los ficheros abiertos del proceso padre.
• Se copian los descriptores de archivos abiertos.
• Se desactivan las alarmas pendientes.
• Devuelve:
– -‐1 el caso de error.
– En el proceso padre: el identificador del proceso hijo.
– En el proceso hijo: 0
19
Servicio fork
Proceso A
FORK
Proceso A’
20
Servicio exec
• Servicio único pero múltiples funciones de biblioteca.
• int execl(const char *path, const char *arg, ...);
int execv(const char* path, char* const argv[]); const envp[]);
int execve(const char* path, char* const argv[], char*
int execvp(const char *file, char *const argv[])
• Cambia la imagen del proceso actual.
– path: Ruta al archivo ejecutable.
– file: Busca el archivo ejecutable en todos los directorios especificados por
PATH.
• Descripción:
– Devuelve -‐1 en caso de error, en caso contrario no retorna.
– El mismo proceso ejecuta otro programa.
– Los ficheros abiertos permanecen abiertos.
– Las señales con la acción por defecto seguirán por defecto, las señales con
manejador tomarán la acción por defecto.
21
Servicio fork
Proceso A
EXEC
Proceso B
Proceso A’
22
Servicio exit
• Finaliza la ejecución del proceso.
• void exit(status);
• Se cierran todos los descriptores de ficheros abiertos.
• Se liberan todos los recursos del proceso.
• Se libera el BCP del proceso.
23
Ejemplo: Ejecución de un mandato
#include <sys/types.h>
#include
<stdio.h> int
main() {
pid_t pid;
int
status;
pid = fork();
if (pid == 0) { /* proceso hijo */
execlp("ls","ls","-
l",NULL); exit(-1);
}
else /* proceso padre
*/ printf(“Fin del padre\n”);
retunr 0; /* Invoca a exit(0) */
}
24
Contenidos
• Llamadas al sistema
• Servicios para procesos
• Servicios para archivos y directorios
25
Operaciones genéricas sobre ficheros
• crear: Crea un fichero con un nombre y unos atributos.
• borrar: Borra un fichero a partir de su nombre.
• abrir: Abre un fichero a partir de su nombre para
permitir operaciones de acceso.
• cerrar: Cierra un fichero abierto.
• leer: Lee datos de un fichero abierto a un almacén en
memoria.
• escribir: Escribe datos a un fichero abierto desde un
almacén en memoria.
• posicionar: Mueve el apuntador usado para acceder al
fichero, afectando a operaciones posteriores.
• control: Permite manipular los atributos de un fichero.
26
Servicios POSIX para ficheros
• Visión lógica:
– Un fichero
• Se mantiene un puntero asociado a cada fichero abierto.
– El puntero indica la posición a partir de la cual se realizará la siguiente
operación.
• La mayor parte de las operaciones trabajan con descriptores
de ficheros:
– Un número entero entre 0 y 64K.
– Se obtiene al abrir el fichero (open).
– El resto de operaciones identifican el fichero por su descriptor.
• Descriptores predefinidos:
– 0: entrada estándar
– 1: salida estándar
– 2: salida de error
27
Servicios POSIX para ficheros
• Cada proceso tiene asociada una tabla de ficheros abiertos.
• Cuando se duplica un proceso (fork):
– Se duplica la tabla de archivos abiertos.
– Se comparte la tabla intermedia de nodos-‐i y posiciones.
Proceso P2
Proceso P1
0 50
0 50 12
1
1 12 2 2
2 2 3 215
3 215 nodo-i Posición fd
fd
20 1534
Protección:
dueño grupo mundo
rwx rwx rwx
Ejemplos: 755 indica rwxr-xr-x 30
Ficheros, directorios y servicios en POSIX
• Tipos de fichero:
– Normales .
– Directorios.
– Especiales.
• Nombres de fichero y directorio:
– Nombre completo (empieza por /)
• /usr/include/stdio.h
– Nombre relativo al directorio actual (no empieza por /)
• stdio.h asumiendo que /usr/include es el directorio
actual.
– La entradas . y .. pueden utilizarse para formar rutas de
acceso
• ../include/stdio.h
29
CREAT – Creación de fichero
• Servicio:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int creat(char *name, mode_t mode);
• Argumentos:
– name Nombre de fichero
– mode Bits de permiso para el fichero
• Devuelve:
– Devuelve un descriptor de fichero ó -‐1 si error.
30
CREAT – creación de fichero
• Descripción:
– El fichero se abre para escritura.
– Si no existe crea un fichero vacio.
• UID_dueño = UID_efectivo
• GID_dueño = GID_efectivo
– Si existe lo trunca sin cambiar los bits de permiso.
• Ejemplos:
fd = creat("datos.txt", 0751);
fd = open("datos.txt",
O_WRONLY | O_CREAT | O_TRUNC, 0751);
31
UNLINK – Borrado de fichero
• Servicio:
#include <unistd.h>
int unlink(const char* path);
• Argumentos:
– path nombre del fichero
• Devuelve:
– Devuelve 0 ó -‐1si error.
• Descripción:
– Decrementa el contador de enlaces del fichero. Si el
contador es 0, borra el fichero y libera sus recursos.
32
OPEN – Apertura de fichero
• Servicio:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(char *name, int flag, ...);
• Argumentos:
– name puntero al nombre del fichero
– flags opciones de apertura:
• O_RDONLY Sólo lectura
• O_WRONLY Sólo escritura
• O_RDWR Lectura y escritura
• O_APPEND El puntero de acceso se desplaza al final del fichero
abierto
• O_CREAT Si no existe no tiene efecto. Si no existe lo crea
• O_TRUNC Trunca si se abre para escritura
33
Open – Apertura de fichero
• Devuelve:
– Un descriptor de fichero ó -‐1 si hay error.
• Ejemplos:
fd = open("/home/juan/datos.txt");
fd = open("/home/juan/datos.txt",
O_WRONLY | O_CREAT | O_TRUNC, 0750);
34
CLOSE – Cierre de fichero
• Servicio:
int close(int fd);
• Argumentos:
– fd descriptor de fichero
• Devuelve:
– Cero ó -‐1 si error.
• Descripción:
– El proceso pierde la asociación a un fichero.
35
READ – Lectura de fichero
• Servicio:
#include <sys/types.h>
ssize_t read(int fd, void *buf, size_t n_bytes);
• Argumentos:
– fd descriptor de fichero
– buf zona donde almacenar los datos
– n_bytes número de bytes a leer
• Devuelve:
– Número de bytes realmente leídos ó -‐1 si error
• Descripción:
– Transfiere n_bytes. Puede leer menos datos de los solicitados si se rebasa
el fin de fichero o se interrumpe por una señal.
– Después de la lectura se incrementa el puntero del fichero con el número de
bytes realmente transferidos.
36
WRITE – Escritura de fichero
• Servicio:
#include <sys/types.h>
ssize_t write(int fd, void *buf, size_t n_bytes);
• Argumentos:
– fd descriptor de fichero
– buf zona de datos a escribir
– n_bytes número de bytes a escribir
• Devuelve:
– Número de bytes realmente escritos ó -‐1 si error
• Descripción:
– Transfiere n_bytes. Puede escribir menos datos de los solicitados si se
rebasa el tamaño máximo de un fichero o se interrumpe por una señal.
– Después de la escritura se incrementa el puntero del fichero con el
número de bytes realmente transferidos.
– Si se rebasa el fin de fichero el fichero aumenta de tamaño.
37
LSEEK – Movimiento del puntero de posición
• Servicio:
#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t offset, whence);
int
• Argumentos:
– fd Descriptor de fichero
– offset desplazamiento
– whence base del desplazamiento
• Devuelve:
– La nueva posición del puntero ó -‐1 si error.
• Descripción:
– Coloca el puntero de acceso asociado a fd
– La nueva posición se calcula:
• SEEK_SET posición = offset
• SEEK_CUR posición = posición actual + offset
• SEEK_END posición = tamaño del fichero + offset
40
FNCTL – Modificación de atributos
• Servicio:
#include <sys/types.h>
int fnctl(int fildes, int cmd /* arg*/ ...);
• Argumentos:
– fildes descriptor de ficheros
– cmd mandato para modificar atributos, puede haber
varios.
• Devuelve:
– 0 para éxito ó -‐1 si error
• Descripción:
– Modifica los atributos de un fichero abierto.
39
DUP – Duplicación de descriptor de fichero
• Servicio:
int dup(int fd);
• Argumentos:
– fd descriptor de fichero
• Devuelve:
– Un descriptor de fichero que comparte todas las propiedades del fd ó
-‐1si error.
• Descripción:
– Crea un nuevo descriptor de fichero que tiene en común con el
anterior:
• Accede al mismo fichero
• Comparte el mismo puntero de posición
• El modo de acceso es idénBco.
– El nuevo descriptor tendrá el menor valor numérico posible.
40
FTRUNCATE – Asignación e espacio a un fichero
• Servicio:
#include <unistd.h>
int ftruncate(int fd, off_t length);
• Argumentos:
– fd descriptor de fichero
– length nuevo tamaño del fichero
• Devuelve:
– Devuelve 0 ó -‐1si error.
• Descripción:
– El nuevo tamaño del fichero es length. Si length es 0
se trunca el fichero.
41
STAT – Información sobre un fichero
• Servicio:
#include <sys/types.h>
#include <sys/stat.h>
int stat(char *name, struct stat *buf);
int fstat(int fd, struct stat *buf);
• Argumentos:
– name nombre del fichero
– fd descriptor de fichero
– buf puntero a un objeto de tipo struct stat donde
se almacenará la información del fichero.
• Devuelve:
– Cero ó -‐1 si error
42
STAT – Información sobre un fichero
• Descripción:
– Obtiene información sobre un fichero y la almacena en una estructura
de tipo struct stat:
struct stat {
mode_t st_mode; /* modo del fichero */
ino_t st_ino; /* número del fichero */
dev_t st_dev; /* dispositivo */
nlink_t st_nlink; /* número de enlaces */
uid_t st_uid; /* UID del propietario */
gid_t st_gid; /* GID del propietario */
off_t st_size; /* número de bytes */
time_t st_atime; /* último acceso */
time_t st_mtime; /* última modificacion */
time_t st_ctime; /* último modificacion de datos
*/
};
43
STAT – Información sobre un fichero
• Comprobación del tipo de fichero aplicado a
st_mode:
S_ISDIR(s.st_mode) Cierto si directorio
S_ISCHR(s.st_mode) Cierto si especial de caracteres
S_ISBLK(s.st_mode) Cierto si especial de bloques
S_ISREG(s.st_mode) Cierto si fichero normal
S_ISFIFO(s.st_mode) Cierto si pipe o FIFO
44
UTIME – Alteración de atributos de fecha
• Servicio:
#include <sys/stat.h>
#include <utime.h>
int utime(char *name, struct utimbuf *times);
• Argumentos:
– name nombre del fichero
– times estructura con las fechas de último acceso y modificación.
• time_t actime fecha de acceso
• time_t mctime fecha de modificación
• Devuelve:
– Devuelve 0 ó -‐1sierror
• Descripción:
– Cambia las fechas de último acceso y última modificación según los
valores de la estructura struct utimbuf
45
Ejemplo: Copia de un fichero en otro
#include <sys/types.h>
#include <sys/stat.h> /* abre el fichero de entrada */
fd_ent = open(argv[1], O_RDONLY);
#include <fcntl.h>
if (fd_ent < 0) {
#include <stdio.h> perror("open");
exit(-1);
#define BUFSIZE 512
}
/* crea el fichero de salida */
main(int argc, char **argv) fd_sal = creat(argv[2], 0644); if
{ int fd_ent, fd_sal; (fd_sal < 0) {
close(fd_ent);
char
perror("open");
buffer[BUFSIZE]; int exit(-1);
n_read; }
46
Ejemplo: Copia de un fichero en otro
/* bucle de lectura del fichero de entrada */
while ((n_read = read(fd_ent, buffer, BUFSIZE)) > 0) {
/* escribir el buffer al fichero de salida */
if (write(fd_sal, buffer, n_read) < n_read) {
perror("write2);
close(fd_ent); close(fd_sal);
exit(-1);
}
}
if (n_read < 0) {
perror("read");
close(fd_ent); close(fd_sal);
exit(-1);
}
close(fd_ent); close(fd_sal);
exit(0);
}
47
Ejemplo: Redirección (ls > fichero)
void main(void)
{ pid_t pid;
int
status;
int fd;
fd = open("fichero", O_WRONLY|O_CREAT|O_TRUNC, 0644);
if (fd < 0) {
perror("open");
exit(-1);
}
pid = fork();
50
Servicios POSIX para directorios
• Visión lógica:
– Un directorio es un fichero con registros Bpo estructura DIR
– Por tanto se pueden operar como un fichero, pero !NO SE PUEDEN ESCRIBIR
DESDE PROGRAMA, SOLO LEER!
• Estructura DIR:
– d_ino; // Nodo_i
– d_off; // Posición en el fichero del elemento del directorio
– d_reclen; // Tamaño del directorio
– d_type; // Tipo del elemento
– d_name[0]; // Nombre del fichero de longitud variable
– ¡Ojo! Al ser el nombre de longitud variable no se pueden manipular
como registros de longitud fija
– Solución: llamadas al sistema para manejar directorios
49
Servicios POSIX para directorios
• DIR *opendir(const char *dirname);
– Abre el directorio y devuelve un puntero al principio de Bpo DIR
• int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result);
– Lee la siguiente entrada de directorio y la devuelve en una struct dirent
• long int telldir(DIR *dirp);
– Indica la posición actual del puntero dentro del archivo del directorio
• void seekdir(DIR *dirp, long int loc);
– Avanza desde la posición actual hasta la indicada en “loc”. Nunca saltos atras.
• void rewinddir(DIR *dirp);
– Resetea el puntero del archivo y lo pone otra vez al principio
• int closedir(DIR *dirp);
– Cierra el archivo del directorio
50
Proyección en POSIX
• void *mmap(void *direc, size_t lon, int prot,
int flags, int fd, off_t desp);
• Establece proyección entre espacio de direcciones de un
proceso y un archivo.
– Devuelve la dirección de memoria donde se ha proyectado el
archivo.
– direc: dirección donde proyectar. Si NULL SO elige una.
– lon: especifica el número de bytes a proyectar
– prot: Protección para la zona (se pueden combinar con |).
– flags: Propiedades de la región.
– fd: Descriptor del fichero que se desea proyectar en memoria.
– desp: Desplazamiento inicial sobre el archivo.
51
Proyección POSIX: mmap
• Tipos de protección:
– PROT_READ: Se puede leer.
– PROT_WRITE: Se puede escribir.
– PROT_EXEC: Se puede ejecutar.
– PROT_NONE: No se puede acceder a los datos.
• Propiedades de una región de memoria:
– MAP_SHARED: La región es comparBda. Las modificaciones
afectan al fichero. Los procesos hijos comparten la región.
– MAP_PRIVATE: La región es privada. El fichero no se modifica.
Los procesos hijos obtienen duplicados no compartidos.
– MAP_FIXED: El fichero debe proyectarse en la dirección
especificada por la llamada.
52
Proyección POSIX
desp len
Proceso
53
Desproyección en POSIX
• void munmap(void *direc, size_t lon);
– Desproyecta parte del espacio de direcciones de un
proceso desde la dirección direc hasta direc+lon.
54
Ejemplo: Contar el número de blancos en un fichero
#include <sys/types.h>
#include <sys/stat.h> vec = mmap(NULL, dstat.st_size,
#include <sys/mman.h> PROT_READ, MAP_SHARED, fd, 0);
#include <fcntl.h> close(fd);
#include <stdio.h> c =vec;
#include <unistd.h> for (i=0;i<dstat.st_size;i++) {
if (*c==‘ ‘) {
int main() { n++;
int fd; }
struct stat dstat; c++;
int i, n; }
char c, munmap(vec, dstat.st_size);
char * vec; printf(“n=%d,\n”,n);
return 0;
fd = open(“datos.txt”,O_RDONLY); }
fstat(fd, &dstat);
55
Ejemplo: Copia de un fichero
#include <sys/types.h>
vec1=mmap(0, bstat.st_size,
#include <sys/stat.h>
PROT_READ, MAP_SHARED, fd1,0);
#include <sys/mman.h>
vec2=mmap(0, bstat.st_size,
#include <fcntl.h>
PROT_READ, MAP_SHARED, fd2,0);
#include <stdio.h>
#include <unistd.h>
close(fd1); close(fd2);
int main() {
p=vec1; q=vec2;
int i, fd1, fd2;
for (i=0;i<dstat.st_size;i++) {
struct stat dstat;
*q++ = *p++;
char * vec1, *vec2, *p, *q;
}
fd1 = open(“f1”, O_RDONLY);
munmap(fd1, bstat.st_size);
fd2 = open(“f2”, O_CREAT|O_TRUNC|O_RDWR,0640);
munmap(fd2, bstat.st_size);
fstat(fd1,&dstat);
ftruncate(fd2, dstat.st_size);
return 0;
}
56