Sistemas Operativos
Tema 2
Interfaces del sistema Operativo. Llamadas al sistema
Para gestión de procesos
Relacionadas con señales
Para gestión de ficheros
Para gestión de directorios
Para protección
Punto 6. Llamadas al sistema (SYSTEM CALLS)
Acceso al SOP a través de una interrupción software.
ejemplo:
open() es una unción de librería de C que genera una interrupción soft. read() en realidad no 'toca' para nada el disco. Consiste en
read ( . . . ) {
paso de parámetros trap
devolución de parámetros }
Las funciones del SOP trabajan sobre las dos abstracciones: proceso y fichero Proceso:
- Manejo de procesos y memoria - Señales Fichero: - Manipulación de ficheros - Directorios - Protección de ficheros Tiempo
Llamadas al sistema para gestión de procesos: fork, wait, exec, exit, brk, getpid
pid = fork ()
pid del proceso hijo o 0 crea un proceso con copia de la imagen en memoria del padre Genera un proceso hijo que hereda del padre el core image:
1. UID y GID reales y efectivos
2. Descriptores de ficheros. Todos los ficheros que tiene abiertos el padre también los tiene el hijo.
3. Gestión de señales. Igualmente a los descriptores 4. Directorio de trabajo
5. Máscara de protección 6. Contador de programa Diferencias entre hijo y padre:
1. PID. Es un proceso diferente 2. PPID. Tiene un padre distinto
3. Se anulan posibles alarmas pendientes
Importante: Las variables son copias, no son compartidas.
fork devuelve en pid: 0 en el proceso hijo.
-1 caso de no haberse podido crear al hijo. Identificador del hijo en el proceso padre
ejemplo:
while (TRUE) { // bucle infinito
leer_comando(comando,parametros); // lee del
terminal
if (fork() != 0) { // crea proceso hijo
wait(&status); // código que sigue ejecutando el padre }
else {
execve(comando,parametros,0) // código que sigue ejecutando el hijo }
pid = wait ( &status );
pid del hijo que ejecuta exit
exit ( status );
El proceso padre la ejecuta el proceso hijo cuando finaliza su ejecución
estado de finalización estado del hijo
16 bits
estado de finalización espera al hijo
Valor de status:
-1 => El padre no tiene ningún hijo 0 => El hijo ha terminado normalmente
Posibilidades:
1º.- Padre ejecuta wait y después el hijo ejecuta exit.
Padre => espera a que termine el hijo antes de continuar.
Hijo => ejecuta exit.
Padre => mata a su hijo.
2º.- Hijo ejecuta exit y después el padre ejecuta wait
Hijo => finaliza la ejecución pero no es destruido.
En este estado al hijo se le denomina ZOMBIE Padre => ejecuta wait y destruye al hijo.
Padre
Hijo_1 Hijo_2 Hijo_3
Padre
Hijo_1
Hijo_N
Figura (a) Figura (b)
En fig a si el padre ejecuta wait, no se puede saber a qué hijo está esperando, de forma que esperará a que termine alguno
En fig b si el padre ejecuta wait y el Hijo_1 ejecuta exit, el proceso Hijo_N se queda huérfano, con lo que su padre pasaría a ser el proceso INIT.
Es importante que un nodo tenga padre, de otra manera, no será destruido. INIT deberá efectuar un bucle infinito con la sentencia wait, para que todos los hijos que tenga y adopte, pueda destruirlos, cuando finalicen su ejecución. Existe, en este punto, una diferencia importante entre UNIX y MINIX:
- En fig b, si Hijo_1 ejecuta exit, automáticamente se queda ZOMBIE. - En MINIX, INIT no adopta a Hijo_N hasta que Hijo_1 no es destruido - En UNIX, INIT adopta a Hijo_N cuando Hijo_1 se queda ZOMBIE.
s = execve ( nombre, argv, envp );
-1 caso de error
cambia la imagen del proceso que la invoca
fichero a ejecutar
puntero a vector de variables de entorno puntero a vector de
argumentos
Todos los atributos permanecen salvo dos:
- Tratamiento de la señales capturadas, es decir, si se había ejecutado signal(sig,f) para asociar la ejecución de la función f a la señal sig, ahora tomará la función por defecto SIB_DFL.
- Si el fichero ejecutable tiene un bit SETUID activo, el UID efectivo del proceso se asigna al owner UID del fichero.
tam = brk ( dirección )
establece nueva dirección de terminación del segmento de datos
dirección final del segmento de datos tamaño del segmento
de datos
pid = getpid ( )
proporciona el identificador de un proceso
Llamadas al sistema relacionadas con señales: signal, kill, alarm, pause
- Si un proceso recibe una señal que no estaba esperando, se mata al proceso - Cuando la señal es esperada, se trata en segundo nivel de interrupción
- Después de recibir una señal hay que reactivar la captura para que siga siendo efectiva
funcant = signal ( señal, func )
habilita al proceso para el tratamiento de señales
señal anterior tratamiento
(SIG_DFL, SIG_IGN, . . . ) nombre de la señal
a capturar
s = kill ( pid, señal )
envía una señal a un proceso
(SIGKILL no puede capturarse ni ignorarse)
señal enviada pid destinatario
-1 caso de error
residual = alarm ( segundos )
tiempo restante envía SIGALRM
(cancela anterior)
s = pause ()
suspende al ejecutor
hasta la siguiente señal
Llamadas al sistema para gestión de ficheros: creat, mknod, open, close, read, write, lseek, stat, fstat, dup, pipe, ioctl
fd = creat ( nombre, modo )
crea un fichero y lo deja abierto para escritura
descriptor fichero creado código octal de permisos
fd = mknod ( nombre, modo, direccion )
crea un fichero especial o un directorio (sólo superusuario)
descriptor fichero especial creado
0111111 tipo (car. ó bloq.)
permisos
0x1111
número secundario número principal
fd = open ( nombre, acceso )
abre un fichero
descriptor fichero a abrir
( 0 lectura ) ( 1 escritura ) ( 2 lect./escrit. ) s = close ( fd ) cierra un fichero descriptor de fichero
n = read ( fd, buffer, nbytes )
lee de un fichero
cantidad leida
descriptor de fichero
buffer destino cantidad a leer
n = write ( fd, buffer, nbytes )
escribe en un fichero
cantidad escrita
descriptor de fichero
buffer origen
cantidad a escribir
pos = lseek ( fd, posición, referencia )
posición absoluta
descriptor de fichero
posición relativa a
base para posicionar posicionamiento del puntero de un fichero
la referencia
(principio, final, actual) en el fichero
s = stat ( nombre, &buffer )
obtiene el estado de un fichero
s = fstat ( fd, &buffer )
descriptor del fichero
Puntero a destino
El contenido de buffer es: struct stat {
short st_dev; // dispositivo dende reside el nodo-i unsigned short st_ino; // número del nodo-i
unsigned short st_mode; // códigos de protección (modo) short st_nlink; // número de enlaces
short st_uid; // identificador del propietario short st_gid; // identificador del grupo
short st_rdev; // número ppal/sec en ficheros especiales long st_size; // tamaño del fichero
long st_atime; // idéntico a st_mtime
long st_mtime; // instante de la última modificación long st_ctime; // idéntico a st_mtime
};
Estructura de datos utilizada por STAT y FSTAT para devolver información. Existen tres campos relacionados con tiempo por razones de compatibilidad con UNIX.
fd = dup ( fd1 )
duplica el descriptor de un fichero
nuevo descriptor del
mismo fichero descriptor originaldel fichero Redireccionar_salida (s) char *s; { int fd; fd = creat (s,0666); close (STD_OUTPUT); dup (fd); close (fd); } Redireccionar_entrada (e) char *e; { int fd;
fd = open (e, RD_ONLY); close (STD_INPUT); dup (fd);
close (fd); }
s = pipe ( &fd[0] )
fd[0] descriptor para lectura crea un pipe
fd[1] descriptor para escritura
Ejemplo: Esqueleto de programa para disponer dos procesos en cadena. # define STD_INPUT 0 // descriptor de fichero entrada estandar # define STD_OUTPUT 1 // descriptor de fichero salida estandar cadena(proceso1, proceso2)
char *proceso1, *proceso2; // punteros a nombres de programa {
int fd[2]; pipe(&fd[0]); if (fork() != 0) {
close(fd[0]); // el proceso 1 no ha de leer del tubo close(STD_OUTPUT); // preparación de la nueva salida estandar dup(fd[1]); // salida estandar vinculada a fd[1]
close(fd[1]); // ya no se necesita más el tubo execl(proceso1,proceso2,0);
} else {
close(fd[1]); // el proceso 2 no escribe en el tubo
close(STD_INPUT); // preparación de la nueva entrada estandar dup(fd[0]); // entrada estandar vinculada a fd[0]
close(fd[0]); // ya no se necesita más el tubo execl(proceso2, proceso2,0)
} }
s = iotcl ( fd, petición, &argp )
operaciones particulares en ficheros especiales
descriptor de fichero especial
función a realizar
puntero a registro de bits de estado
Llamadas al sistema para gestión de directorios: link, unlink, mount, umount, sync, chdir, chroot
s = link ( nombre, enlace )
asocia un nodo-i existente a un nuevo nombre
nombre del fichero nombre del enlace
16 81 40 correo juegos prueba /usr/ast 31 70 59 bin memo f.c /usr/jim 38 prog1 16 81 40 correo juegos prueba /usr/ast 31 70 59 bin memo f.c /usr/jim 38 prog1 70 nota
(a) Dos directorios antes de enlazar /usr/jim/memo al directorio de ast. (b) Los mismos directorios después del enlace
(a) (b)
s = unlink ( nombre )
anula la asociación de nombre con el nodo-i
nombre del fichero que se borra
s = mount ( especial, nombre, rwindic )
monta un sistema de ficheros en otro
nombre de fichero especial de bloques
s = unmount ( especial )
desmonta un sistema de ficheros
nombre de fichero especial de bloques
s = sync ()
copia modificaciones de caché a disco (ejecutada por 'update')
s = chdir ( nombre )
cambia el directorio de trabajo
nuevo directorio de trabajo
s = chroot ( nombre )
cambia el directorio raiz
nuevo directorio raiz (sólo superusuario)
Llamadas al sistema para protección: chmod, getuid, getgid, setuid, setgid, chown, umask, access
s = chmod ( nombre, modo )
cambia la protección de un fichero
fichero 0 1 1 1
usuario grupo otros
s = getuid ()
obtiene el usuario efectivo
s = getgid ()
obtiene el grupo efectivo
s = setuid ( uid )
asigna valor al uid del proceso llamador (sólo superusuario)
nuevo valor del uid
s = setuid ( uid )
asigna valor al gid del proceso llamador (sólo superusuario)
nuevo valor del gid
s = chown ( nombre, propietario, grupo )
cambia el usuario y grupo de un fichero
fichero nuevo propietario nuevo grupo
anterior = umask ( máscara )
inhibe permiso (los hijos heredan la máscara)
s = access ( nombre, modo )
comprueba si uid real tiene permiso
fichero 0 1 4 lectura 2 escritura 1 ejecución 0 comprueba accesibilidad
Llamadas al sistema para gestión de tiempo: time, stime, utime, times
segundos = time ( &segundos )
obtiene el tiempo desde 1.1.1970 en seg.
s = stime ( tp )
ajusta la hora. (sólo superusuario)
s = utime ( fichero, instante )
actualiza el valor de st_mtime en el nodo_i de un fichero
s = times ( buffer )
tiempo de procesador consumido por un proceso y por el sistema en su nombre y el total acumulado de los hijos