Nothing Special   »   [go: up one dir, main page]

Introduccion Posix Portable Operating System Interface Unix

Descargar como ppt, pdf o txt
Descargar como ppt, pdf o txt
Está en la página 1de 38

Introducción a POSIX

Introducción
 POSIX son un conjunto de normas IEEE/ISO que
definen la interfaz entre las aplicaciones y el SSOO
 POSIX: Portable Operating System Interface + UniX
 Su objetivo es conseguir la portabilidad de las
aplicaciones a nivel de código fuente
 La aplicación puede desarrollarse en C, Ada,
Fortran y otros lenguajes
 Las normas definen los servicios que cada sistema
operativo particular puede incluirlos o no
 La denominación oficial es IEEE Std. 1003, e
ISO/IEC-9945
POSIX: estándares base (C)
 POSIX 1, 1a Unix básico sin tiempo real
 POSIX 1b, 1d, 1i, 1j Extensiones de tiempo real
 POSIX 1c Extensiones de threads
 POSIX 1e Seguridad
 POSIX 1f Network File System
 POSIX 1g Servicios de red (sockets)
 POSIX 1h Tolerancia a fallos
 POSIX 21 Comunicaciones de TR
POSIX: interfaz otros lenguajes
 POSIX 5, 5a, 5b Interfaces con Ada
 POSIX 9 Interfaces con Fortran 77
POSIX: perfiles de entornos
 POSIX 10 Supercomputadores
 POSIX 13 Tiempo real
 POSIX 14 Multiprocesadores
 POSIX 18 Estación de trabajo POSIX
POSIX de tiempo real ¿para qué?
 Existe gran diversidad de sistemas de TR:
 Núcleos de TR (LynxOS, VxWorks, QNX, etc.)
 Ejecutivos Ada
 En sistemas grandes: VMS y otros
 Era necesario definir un estándar que asegurase la
portabilidad de aplicaciones a nivel de código fuente
entre diferentes entornos de tiempo real
Perfiles de entornos de aplicación
 PSE50: sistema de tiempo real mínimo
 Sólo procesos ligeros, sin gestión de memoria ni
archivos ni terminal
 PSE51: controlador de tiempo real
 Añade el terminal y sistema de archivos
 PSE52: sistema de tiempo real dedicado
 Soporta procesos pesados y gestión de memoria
 PSE53: sistema de tiempo real generalizado
 Sistema completo con todos los servicios
Características de los perfiles

Perfil Sistema de Múltiples Threads


archivos procesos
Sistema mínimo NO NO SÍ

Controlador SÍ NO SÍ

Sistema dedicado NO SÍ SÍ

Sistema multipropósito SÍ SÍ SÍ
POSIX: Unix básico
 POSIX 1 define los servicios ofrecidos por Unix:
 Gestión de procesos:
 Creación y destrucción
 Sincronización
 Temporización
 Gestión de archivos
 Creación y borrado de archivos y directorios
 Trabajo con archivos especiales
 Protección de la información
 Entrada-salida y control
POSIX: Extensiones de TR
 Para obtener determinismo en el comportamiento
 Planificación
 Gestión de memoria
 Señales
 Relojes y temporizadores
 Para facilitar la concurrencia
 Sincronización
 Memoria compartida
 Colas de mensajes
 Entrada-salida síncrona y asíncrona
POSIX: Extensiones de threads
 POSIX 1c incorpora funciones para trabajar con
hilos. Incluye:
 Gestión de hilos
 Sincronización de hilos
 Planificación de hilos
 Creación y destrucción de hilos
 Añade reentrada a algunas funciones de POSIX1
 POSIX 1c puede hacer uso de funciones incluidas
en POSIX 1 y POSIX 1b
Definiciones
 Programa
 Archivo ejecutable residente en un dispositivo de
almacenamiento permanente
 Se ejecuta por medio de la llamada exec()

 Proceso
 Es un programa en ejecución
 Los procesos se crean con la llamada fork()

 Servicios del sistema operativo


 Invocados por medio de funciones
 POSIX no diferencia entre llamadas al sistema y
procedimientos de biblioteca
Estructura de un proceso en C
Proceso de usuario

Funciones

main()

Rutina de inicio exit() _exit()

Llamada al sistema exec()

Núcleo
Ejemplo
/**************************************
* Programa que imprime todos los *
* argumentos de línea de órdenes *
**************************************/
int main (int argc, char *argv[])
{
int i;
for (i=0; i<argc; i++)
printf (“%s\n”, argv[i]);
exit(0);
} /* Fin de main */
Características de un proceso
 Cada proceso se caracteriza por una estructura de
datos conocida como tabla de control de tarea que
contiene:
 Identificador de proceso o PID
 Identificador de proceso padre o PPID
 Identificador de usuario o UID
 Identificador de grupo o GID
 Puntero a la memoria asignada
 Puntero a los recursos ...
 Cada proceso dispone de un espacio de
direccionamiento virtual independiente
Creación de procesos: fork()

 La llamada fork() crea una copia (hijo) del


proceso que la invoca
 El hijo hereda del padre:
 Estado
 Semáforos
 Objetos de memoria
 Política de planificación, etc.
 El hijo no hereda:
 El PID
 Alarmas y temporizadores
 Operaciones de E/S asíncronas
Interfaz de fork()

 Definida en:
#include <sys/types.h>
pid_t fork(void);
 Valores de retorno:
 Al padre: el PID del hijo
 Al hijo: cero
 En caso de error: devuelve -1 y la variable
errno contiene el valor asociado al error
Ejemplo con fork()
#include <sys/types.h>
int main(void) {
pid_t id;
id = fork();
if (id == -1) {
perror (“Error en el fork”);
exit (1);
}
if (id == 0) {
while (1) printf (“Hola: soy el hijo\n”);
} else {
while (1) printf (“Hola: soy el padre\n”);
}
} /* Fin de main */
Ejecución de programas: exec()

 La familia de llamadas exec() se emplea para


cargar la imagen de un proceso desde un archivo a
memoria
 La nueva imagen se carga encima de la del proceso
que invoca la llamada, machacándolo
 El nuevo proceso hereda:
 El PID y el PPID del proceso original
 La política de planificación
 Las alarmas y señales pendientes
Prototipos de la familia exec()

 Definidos en:
#include <unistd.h>
int execl (const char *path,
const char *arg, ...);
int execlp (const char *file,
const char *arg, ...);
int execle (const char *path, const char *arg,
..., char * const envp[]);
int execv (const char *path, char const *argv[]);
int execvp (const char *file, char const *argv[]);
Valores de retorno:
 En caso de error exec() devuelve -1
Ejemplo con exec()
#include <unistd.h>
int main(void) {
int ret;
char *arg[3];
arg[0] = “ls”;
arg[1] = “-l”;
arg[2] = (char *)0;
printf (“Allá va!\n”);
ret = execv (“/bin/ls”, arg);
if (ret == -1) {
perror (“Error en el exec”);
exit (1);
}
} /* Fin de main */
Finalización de procesos: exit()

 La llamada exit() provoca la finalización del


proceso que la invoca
 Esta llamada nunca retorna
 Cuando un proceso termina, sus hijos no mueren y
suelen ser adoptados por el proceso init
 Prototipo definido en:
#include <unistd.h>
void _exit (int status);
 El valor status es retornado al padre si es que
existe
Espera por procesos: wait()

 La llamada wait() permite que un proceso quede


esperando a que sus hijos terminen
 El padre puede conocer el valor de retorno de cada
hijo
 Prototipos definido en:
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait (int *status);
pid_t waitpid(pid_t pid, int *status, int
options);
Ejemplo con wait()
#include <sys/types.h>
#include <sys/wait.h>
int main(void)
{
pid_t id;
int estado;
id = fork();
if (id == -1) {
perror (“Error en el fork”);
exit (1);
}
Continuación del ejemplo
if (id == 0) {
printf (“Soy el hijo\n”);
sleep(3);
printf (“Hijo: despierta y finaliza\n”);
exit(0);
} else {
printf (“Soy el padre y ahora espero ...\n”);
wait (&estado);
printf (“Padre: el hijo terminó con estado =
%d\n”, estado);
exit (0);
}
} /* Fin de main */
Planificación
 Los mecanismos clásicos de planificación no son
válidos
 Es necesario evitar el indeterminismo
 POSIX 1b utiliza una planificación expulsora con
prioridades fijas (32 como mínimo) con tres políticas
diferentes:
SCHED_FIFO FIFO para tareas de igual prioridad

SCHED_RR Round-Robin en tareas con la misma


prioridad. El quanto es fijo

SCHED_OTHER Definido por la realización concreta


Planificación (continuación)
 Los parámetros de planificación y los prototipos de
las funciones se encuentran en:
#include <sched.h>
 Parámetros de planificación:
struct sched_param {
int sched_priority;
}
 Definir política y parámetros (hay que ser root):
int sched_setscheduler (pid_t pid,int policy,
const struct sched_param *param);
Planificación (continuación)
 Leer la política y los parámetros:
int sched_getscheduler (pid_t pid);
int sched_getparam (pid_t pid,
struct sched_param *param);
 Ceder el procesador:
int sched_yield (void);
 Leer los límites de los parámetros:
int sched_get_priority_max (int policy);
int sched_get_priority_min (int policy);
int sched_rr_get_interval (pid_t pid,
struct timespec *interval);
Ejemplo
#include <sched.h>
#include <sys/types.h>

int main(void) {
pid_t pid;
struct sched_param parametros;
int i, max_prio;
pid = getpid();
max_prio = sched_get_priority_max(SCHED_FIFO);
parametros.sched_priority = max_prio;
sched_setscheduler(pid, SCHED_FIFO, &parametros);
for (i=0; i<100000000; i++);
} /* Fin de main */
Introducción
 La memoria virtual introduce NO determinismo
 POSIX proporciona la posibilidad de bloquear
memoria para evitar la aleatoriedad
 Los procesos a pesar de tener un espacio de
direccionamiento disjunto pueden compartir objetos
de memoria
 La compartición se realiza mapeando la zona de
memoria que deseamos compartir en los espacios
de direccionamiento virtuales de cada proceso
 La compartición se realiza a través de páginas de
modo que el tamaño de una zona proyectada es un
múltiplo del tamaño de la página
Bloqueo de memoria
 Los procesos pueden bloquear todas sus páginas
en memoria para evitar el intercambio con el disco
#include <sys/mman.h>
int mlockall (int flags);
 El valor de flags puede ser:
MCL_CURRENT: afecta a las páginas actuales
MCL_FUTURE: afecta a las páginas futuras
 Para liberar todas las páginas del proceso:
int munlockall (void);
Bloqueo de memoria
 Un proceso pueden bloquear también un rango de
su espacio de direccionamiento
int mlock (const void *addr, size_t len);
 Para desbloquear un rango de direcciones:
int munlock (const void *addr, size_t len);
Memoria compartida
Proceso 1 Proceso 2
Memoria física

M. Compartida

M. Compartida
M. Compartida
Proyección de objetos en memoria
 La llamada mmap() permite proyectar objetos en
memoria
 Estos objetos pueden ser compartidos
 Función mmap():
void *mmap (void *addr, size_t len, int prot,
int flags, int fildes, off_t off);
 El objeto queda identificado por fildes
 len y off son la longitud y el offset del objeto en
bytes respectivamente
 addr es la dirección donde deseamos proyectar el
objeto preferiblemente. Es sólo una indicación
Proyección de objetos en memoria
 La dirección real donde se proyecta el objeto es
devuelta por mmap()y depende del valor de flags:
MAP_FIXED: addr se interpreta de forma exacta, sin este
flag si addr vale NULL, el sistema elige la
dirección
MAP_SHARED: los cambios son compartidos
MAP_PRIVATE: no se comparten los cambios
 prot especifica el tipo de acceso:
PROT_READ: derecho de lectura
PROT_WRITE: derecho de escritura
PROT_EXEC: derecho de ejecución
PROT_NONE: sin derechos
Proyección de objetos en memoria
 Para eliminar la proyección de un objeto en
memoria emplearemos la función munmap()
int munmap (void *addr, size_t len);
Objetos de memoria compartida
 Para abrir un objeto de memoria compartida:
#include <sys/mman.h>
int shm_open (const char *path, int oflag,
mode_t mode );
 Se establece una conexión entre el path que
identifica al objeto y el descriptor devuelto
 oflag determina el modo de acceso
 mode determina los derechos de acceso si creamos
un nuevo objeto
 Es recomendable por razones de portabilidad que el
path comience con el carácter /
Objetos de memoria compartida
 Fijar el tamaño de un objeto de memoria compartida
int ftruncate (int fildes, off_t length);
 Para borrar un objeto de memoria compartida:
int shm_unlink (const char *path);

También podría gustarte