Posix ieee 1003
Download
1 / 129

POSIX IEEE 1003 - PowerPoint PPT Presentation


  • 95 Views
  • Uploaded on

POSIX IEEE 1003. Sebastián Sánchez Prieto. Introducción. POSIX son un conjunto de normas IEEE/ISO que definen la interfaz entre las aplicaciones y el SSOO POSIX: P ortable O perating S ystem I nterface + Uni X

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha
Download Presentation

PowerPoint Slideshow about ' POSIX IEEE 1003' - rhian


An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript
Posix ieee 1003

POSIX IEEE 1003

Sebastián Sánchez Prieto


Introducci n
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: 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: interfaz otros lenguajes

  • POSIX 5, 5a, 5b Interfaces con Ada

  • POSIX 9 Interfaces con Fortran 77


Posix perfiles de entornos
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
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
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
Características de los perfiles

Perfil

Sistema de archivos

Múltiples procesos

Threads

Sistema mínimo

NO

NO

Controlador

NO

Sistema dedicado

NO

Sistema multipropósito


Posix unix b sico
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
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: 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
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
Estructura de un proceso en C

Proceso de usuario

Funciones

main()

Rutina de inicio

_exit()

exit()

exec()

Llamada al sistema

Núcleo


Ejemplo
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
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
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
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
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
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
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
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
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
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
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
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
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

Definido por la realización concreta

SCHED_OTHER


Planificaci n continuaci n
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 n1
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);


Ejemplo1
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 n1
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
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 memoria1
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
Memoria compartida

Proceso 1

Proceso 2

Memoria física

M. Compartida

M. Compartida

M. Compartida


Proyecci n de objetos en memoria
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 memoria1
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: addrse interpreta de forma exacta, sin esteflagsiaddrvaleNULL, 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 memoria2
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
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 compartida1
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);



Introducci n2
Introducción

  • El reloj sirve para medir el paso del tiempo

  • Tick:

    • Unidad del tiempo

    • El número de ticks por segundo se puede conocer con sysconf (_SC_CLK_TCK)

  • Resolución:

    • Mínimo intervalo de tiempo que un reloj puede medir

  • La Época: CUT (Coordinated Universal Time)

    • 0 h 0 m 0s del 1 de enero de 1970


Introducci n3
Introducción

  • Temporizador

    • Es un objeto que puede avisar a los procesos si ha transcurrido cierta cantidad de tiempo o se ha alcanzado cierta hora

    • Cada temporizador está asociado a un reloj

  • Reloj del sistema

    • Mide los segundos desde La Época

    • Mantiene la hora

  • Reloj de tiempo real

    • Se usa para timeouts y temporizadores


Reloj del sistema
Reloj del sistema

  • Leer la hora:

    #include <time.h>

    time_t time (time_t *t);

    • time() devuelve los segundos transcurridos desde La Época

    • Si t es distinto de NULL en él se devuelve la hora también

  • Alarma:

    #include <unistd.h>

    unsigned int alarm (unsigned int seconds);

    • Cuando transcurren los segundos especificados se envía la señal SIGALRM


Ejemplo2
Ejemplo

#include <signal.h>

#include <stdio.h>

#include <unistd.h>

#include <time.h>

void manejador (int senal) {

time_t seg;

printf (“Recibida la señal de alarma ... \n”);

seg = time (NULL);

printf (“Segundos desde La Época: %d\n”, seg);

exit (0);

}


Ejemplo continuaci n
Ejemplo (continuación)

main() {

struct sigaction accion;

time_t seg;

accion.sa_flags = 0;

accion.sa_handler = manejador;

sigemptyset (&accion.sa_mask);

sigaction (SIGALRM, &accion, NULL);

seg = time (NULL);

printf (“Segundos desde La Época: %d\n”, seg);

alarm (3);

while (1);

} /* Fin de main */


Reloj de tiempo real
Reloj de tiempo real

  • La estructura timespec:

    typedef struct timespec {

    time_t tv_sec; /* seconds */

    long tv_nsec; /* nanoseconds */

    } timespec_t;

  • Tiempo = tv_sec * 109 + tv_nsec


Manejo de relojes
Manejo de relojes

  • Cambio de hora:

    #include <time.h>

    int clock_settime(clockid_t clock_id,

    const struct timespec *tp);

  • Obtención de la hora:

    int clock_gettime(clockid_t clock_id,

    struct timespec *tp);

  • Resolución del reloj:

    int clock_getres(clockid_t clock_id,

    struct timespec *res);

  • clockid_t debe valer CLOCK_REALTIME para TR


Ejemplo3
Ejemplo

#include <time.h>

main()

{

struct timespec stime;

clock_getres (CLOCK_REALTIME, &stime);

printf (“Segundos: %d\n”, stime.tv_sec);

printf (“Nanosegundos: %ld\n”, stime.tv_nsec);

} /* Fin de main */


Temporizadores
Temporizadores

  • Se utilizan para generar señales en ciertos momentos o para ejecutar acciones periódicas

  • ¿Cómo crear un temporizador?

    #include <signal.h>

    #include <time.h>

    timer_create(clockid_t clock_id,struct sigevent

    *evp, timer_t *timerid);

  • sigevent indica el modo de aviso: ninguno, señal o crear y ejecutar un hilo

  • timerid es el identificador devuelto

  • El temporizador inicialmente no está activo


Temporizadores1
Temporizadores

  • ¿Cómo borrar un temporizador?

    timer_delete (timer_t timerid);

  • ¿Cómo activar un temporizador?

    int timer_settime (timer_t timerid, int flags,

    const struct itimerspec *value,

    struct itimerspec *ovalue);

  • Estructuraitimerspec:

    it_interval: periodo

    it_value: tiempo de expiración

  • Si it_value vale 0 el temporizador es desactivado

  • Si it_value > 0 el temporizador se activa en el instante especificado


Temporizadores2
Temporizadores

  • Si el temporizador ya estaba activado, se reactiva

  • flag indica si el temporizador es absoluto o relativo

  • Si flag= TIMER_ABSTIME, la primera expiración será cuando el reloj valga it_value

  • Si no se especifica nada, se espera hasta empezar el tiempo definido en it_value

  • ¿Cómo leer el valor de un temporizador?

    int timer_gettime (timer_t timerid,

    struct itimerspec *value);


Ejemplo4
Ejemplo

#include <time.h>

#include <signal.h>

void manejador(int senal) {

struct timespec stime;

clock_gettime (CLOCK_REALTIME, &stime);

printf (“Repeticion -> Segundos: %d\t”,

stime.tv_sec);

printf (“Nanosegundos: %ld\n”, stime.tv_nsec);

} /* Fin de manejador */


Ejemplo5
Ejemplo

main()

{

struct sigaction accion;

struct sigevent evento;

timer_t idtemp;

struct itimerspec itspec;

struct timespec stime;

accion.sa_flags = 0;

accion.sa_handler = manejador;

sigemptyset (&accion.sa_mask);

sigaction (SIGUSR1, &accion, NULL);

evento.sigev_signo = SIGUSR1;

evento.sigev_notify = SIGEV_SIGNAL;


Ejemplo6
Ejemplo

timer_create(CLOCK_REALTIME, &evento,&idtemp);

itspec.it_value.tv_sec=5;/*Activación en 5 s*/

itspec.it_value.tv_nsec = 0;

itspec.it_interval.tv_sec = 1;

itspec.it_interval.tv_nsec = 0;

timer_settime (idtemp, 0, &itspec, NULL);

clock_gettime (CLOCK_REALTIME, &stime);

printf (“Comienzo -> Segundos: %d\t”,

stime.tv_sec);

printf (“Nanosegundos: %ld\n”, stime.tv_nsec);

while(1);

} /* Fin de main */


Ejecuci n
Ejecución

Comienzo -> Segundos: 921550145 Nanosegundos: 828803000

Repetición -> Segundos: 921550150 Nanosegundos: 828918000

Repetición -> Segundos: 921550151 Nanosegundos: 828883000

Repetición -> Segundos: 921550152 Nanosegundos: 828877000

Repetición -> Segundos: 921550153 Nanosegundos: 828891000

Repetición -> Segundos: 921550154 Nanosegundos: 828876000

Repetición -> Segundos: 921550155 Nanosegundos: 828876000

Repetición -> Segundos: 921550156 Nanosegundos: 828877000

Repetición -> Segundos: 921550157 Nanosegundos: 828878000

Repetición -> Segundos: 921550158 Nanosegundos: 828894000

Repetición -> Segundos: 921550159 Nanosegundos: 828880000

Repetición -> Segundos: 921550160 Nanosegundos: 828885000


Sleep
sleep()

  • Se emplea para dormir a un proceso o a un hilo hasta que transcurran lo segundos especificados

    unsigned int sleep (unsigned int seconds);

  • Existe un sleep() de alta resolución

    int nanosleep(const struct timespec *rqtp,

    struct timespec *rmtp);

  • Con nanosleep() se duerme hasta que transcurre el intervalo especificado o hasta que se recibe una señal

    • rqtp es el tiempo que vamos a dormir

    • rmtp es el tiempo que falta por dormir si se retorna por la activación de una señal



Sem foros
Semáforos

  • Es un tipo de dato protegido que se utiliza para acceso exclusivo a recursos compartidos y para sincronización

  • Introducido por Dijkstra a mediados de los 60

  • Si su valor es cero, el semáforo no está disponible

  • Si su valor es positivo, está disponible

  • Operaciones sobre semáforos:

    • P (semáforo);

    • V (semáforo);

  • Existen semáforos con y sin nombre


Funciones asociadas
Funciones asociadas

  • Iniciar un semáforo sin nombre:

    #include <semaphore.h>

    int sem_init(sem_t *sem, int pshared,

    unsigned int value);

    • sem identifica al semáforo

    • pshared determina si sólo puede ser utilizado por hilos del mismo proceso (=0) o se puede compartir entre procesos (!=0)

    • value es el valor inicial del semáforo

  • Destruir un semáforo sin nombre

    int sem_destroy(sem_t *sem);


Funciones asociadas1
Funciones asociadas

  • Iniciar un semáforo con nombre:

    sem_t *sem_open (const char *name, int oflag,

    ... /* mode_t mode, int value */);

    • La función devuelve un puntero al semáforo

    • name debe tener el formato “/name”

    • oflag indica las opciones

      • O_CREAT: si el semáforo no existe, se crea. En este caso se requieren los permisos de acceso (mode) y el valor inicial (value)

      • O_EXCL: si el semáforo existe se produce un error

  • Cerrar un semáforo con nombre

    int sem_close(sem_t *sem);


Funciones asociadas2
Funciones asociadas

  • Borrar un semáforo con nombre:

    int sem_unlink (const char *name);

  • Operación P:

    int sem_wait(sem_t *sem);

    • Si el semáforo está libre, lo toma, en caso contrario, el proceso se bloquea

  • Operación P (con consulta):

    int sem_trywait(sem_t *sem);

    • Toma el semáforo si está libre, en caso contrario devuelve error


Funciones asociadas3
Funciones asociadas

  • Operación V (liberar un semáforo):

    int sem_post (sem_t *sem);

  • Leer el valor de un semáforo:

    int sem_getvalue(sem_t *sem, int *sval);


Ejemplo7
Ejemplo

#include <semaphore.h>

#include <sys/types.h>

#define SEM “/usr/people/chan/src/semaforo”

main() {

sem_t *sem;

pid_t id;

int i;

sem = sem_open (SEM, O_CREAT, 666, 0);

if ((int)sem == -1) {

perror (“Error en sem_open”);

}

id = fork();

if (id == -1) {

perror (“Error en el fork”);


Ejemplo8
Ejemplo

exit (1);

}

if (id == 0) {

for (i=1; i<20; i++) {

printf (“Hijo %d\n”, i);

sem_post (sem);

sleep (1);

}

} else {

for (i=1; i<20; i++) {

sem_wait (sem);

printf (“Padre %d\n”, i);

}

}

} /* Fin de main */



Definici n
Definición

  • Es una información que se transfiere entre diferentes procesos o hilos mediante su inserción o extracción de una cola de mensajes

  • Cada mensaje lleva asociada una prioridad

  • Los mensajes se extraen de la cola de mensajes por orden de prioridad (no FIFO)

  • Las colas de mensajes se identifican por medio de un nombre o un descriptor de cola de mensajes

  • El envío de los mensajes puede ser bloqueante o no bloqueante en función de si el buffer está lleno o vacío


Atributos de las colas
Atributos de las colas

  • Estructura mq_attr

  • Está declarada en <mqueue.h>

    typedef struct mq_attr {

    long mq_flags; /*O_NONBLOCK -> no bloqueante*/

    long mq_maxmsg; /*número máximo de mensajes*/

    long mq_msgsize; /*tamaño máximo del mensaje*/

    long mq_curmsgs; /*actual número de mensajes*/

    } mq_attr_t;


Funciones asociadas4
Funciones asociadas

  • Abrir una cola de mensajes:

    mqd_t mq_open (const char *mq_name, int oflag, ... /* mode_t mode, struct mq_attr *mq_attr */);

    • La función devuelve un descriptor de cola

    • mq_name debe ser del tipo “/name”

    • oflag indica el modo de apertura

    • Con O_CREATmode especifica los derechos y mq_attr los atributos de creación


Funciones asociadas5
Funciones asociadas

  • Cerrar una cola de mensajes:

    mqd_t mq_close (mqd_t mqd);

  • Borrar una cola de mensajes:

    int mq_unlink (const char *mq_name);

  • Definir los atributos de una cola:

    int mq_setattr (mqd_t mqd, struct mq_attr *mqstat,

    struct mq_attr *omqstat);

  • Obtener los atributos de una cola:

    int mq_getattr (mqd_t mqd,

    struct mq_attr *mqstat);


Funciones asociadas6
Funciones asociadas

  • Enviar un mensaje:

    int mq_send (mqd_t mqd, const char *msgptr,

    size_t msglen, unsigned int msg_prio);

    • *msgptr es el puntero al mensaje

    • msglen es su longitud

    • msg_prio es la prioridad del mensaje

  • Recibir un mensaje:

    int mq_receive (mqd_t mqd, char *msgptr,

    size_t msglen, unsigned int *msgprio);


Funciones asociadas7
Funciones asociadas

  • Avisar de la llegada de un mensaje:

    int mq_notify (mqd_t mqd,

    const struct sigevent *notification);

    • cuando llega el mensaje se avisa al proceso del evento

    • sólo se puede avisar a un proceso

    • si el proceso está esperando con mq_receive, la notificación no se produce


Ejemplo9
Ejemplo

#include <mqueue.h>

#include <fcntl.h>

#include <sys/types.h>

#define MQ “/usr/people/chan/src/mesgq”

main()

{

struct mq_attr qattr;

mqd_t qfd;

pid_t id;

int i;

unsigned int Prio;

char Mensaje[20];


Ejemplo10
Ejemplo

qattr.mq_maxmsg = 32;

qattr.mq_msgsize = 20;

qfd = mq_open (MQ, O_CREAT|O_RDWR, 666, &qattr);

if (qfd == -1) {

perror (“Error en mq_open”);

}

id = fork();

if (id == -1) {

perror ("Error en el fork");

exit (1);

}


Ejemplo11
Ejemplo

if (id == 0) {

for (i=1; i<20; i++) {

printf (“Hijo %d\n”, i);

mq_send (qfd, “Hola”, 5, 1);

sleep (1);

}

} else {

for (i=1; i<20; i++) {

mq_receive (qfd, Mensaje, sizeof (Mensaje),

&Prio);

printf (“Padre %d - Mensaje %s\n”, i, Mensaje);

}

}

} /* Fin de main */



Introducci n4
Introducción

  • Un thread es un flujo de control perteneciente a un proceso (a veces se habla de tareas con threads)

  • Se les suele denominar también procesos ligeros, hebras, hilos, etc.

  • La sobrecarga debida a su creación y comunicación es menor que en los procesos pesados

  • Cada hilo pertenece a un proceso pesado

  • Todos los hilos comparten su espacio de direccionamiento

  • Cada hilo dispone de su propia política de planificación, pila y contador de programa


Introducci n5
Introducción

  • Cada hilo tiene su propio identificador tid que sólo es válido para hilos del mismo proceso

  • Una aplicación con hilos puede beneficiarse de un procesamiento paralelo real en sistemas multiprocesador

Hilos

Procesos pesados

Sistema Operativo

Hardware


Operaciones con hilos
Operaciones con hilos

  • Creación y destrucción

  • Sincronización

  • Gestión de prioridades

  • Gestión de señales

  • Gestión de memoria

  • Se pueden utilizar todas las funciones incluidas en POSIX.1 y POSIX.1b

  • La interfaz de hilos POSIX es pthreads, aunque existen otras bibliotecas de hilos


Operaciones asociadas
Operaciones asociadas

  • Crear un nuevo hilo:

    int pthread_create (pthread_t *thread,

    pthread_attr_t *attr,

    void *(*start)(void *),

    void *arg);

    • En thread devuelve el identificador de hilo

    • attr es un puntero a los atributos de la tarea

    • El tercer argumento en un puntero a la función que ejecutará el hilo

    • arg es un puntero a los argumentos del hilo

  • Finalizar un hilo:

    void pthread_exit(void *retval);


Ejemplo12
Ejemplo

#include <pthread.h>

void *Hilo (void *arg) {

printf (“%s\n”, (char *)arg);

pthread_exit (0);

} /* Fin de Hilo */

main()

{

pthread_t th1, th2;

pthread_create (&th1, NULL, Hilo, “Hilo 1”);

pthread_create (&th2, NULL, Hilo, “Hilo 2”);

sleep(5);

puts (“Adios: Hilo principal”);

} /* Fin de main */


Atributos de los threads
Atributos de los threads

  • Los atributos definibles son:

    • Tamaño de la pila

    • Dirección de la pila

    • Control de devolución de recursos

  • Los atributos se crean con:

    int pthread_attr_init(pthread_attr_t *attr);

  • Los atributos se destruyen con:

    int pthread_attr_destroy(pthread_attr_t *attr);


Definici n y obtenci n de attr
Definición y obtención de attr

int pthread_attr_setstacksize(pthread_attr_t

*attr, size_t size);

int pthread_attr_getstacksize(const pthread_attr_t

*attr, size_t *size);

int pthread_attr_setstackaddr(pthread_attr_t

*attr, void *addr);

int pthread_attr_getstackaddr(const pthread_attr_t

*attr, void **addr);

int thread_attr_setdetachstate(pthread_attr_t

*attr, int detach);

int pthread_attr_getdetachstate(const

pthread_attr_t *attr, int *detach);


Devoluci n de recursos
Devolución de recursos

  • Los hilos pueden operar en dos modos diferentes para controlar la devolución de recursos:

    • Detached: opera de modo autónomo, cuando termina devuelve sus recursos (identificador, pila, etc.)

    • Joinable: en su terminación mantiene sus recursos hasta que otro hilo invoca a pthread_join()


Devoluci n de recursos1
Devolución de recursos

  • Los recursos de una tarea joinable se liberan cuando esperamos con pthread_join()

    int pthread_join(pthread_t thread, void **retval);

  • Si la tarea opera en modo detached, el propio hilo al terminar libera sus recursos.

  • Para convertir a un hilo en detached, si no se hizo en su inicio:

    int pthread_detach(pthread_t thread);


Ejemplo13
Ejemplo

#include <pthread.h>

void *Hilo (void *arg) {

printf (“%s\n”, (char *)arg);

sleep(3);

pthread_exit (NULL);

} /* Fin de Hilo */

main()

{

pthread_t th1, th2;

void *st1;

pthread_create (&th1, NULL, Hilo, "Hilo 1");

pthread_join (th1, (void **) &st1);

printf (“Retorno del hilo: %d\n”, st1);

} /* Fin de main */


Identificaci n
Identificación

  • ¿Cómo obtener el identificador del hilo?

    pthread_t pthread_self(void);

  • ¿Cómo comparar identificadores de hilo?

    int pthread_equal(pthread_t thread1,

    pthread_t thread2);

    • Si los identificadores coinciden retorna TRUE, en caso contrario, FALSE


Cancelaci n
Cancelación

  • En cualquier momento se puede solicitar la cancelación de un hilo

  • Cuando se solicita la cancelación de un hilo se puede:

    • Finalizar automáticamente el hilo

    • Ignorar la petición y continuar

    • Retrasar la finalización hasta llegar a un punto seguro


Funciones asociadas8
Funciones asociadas

  • Solicitar la cancelación de un hilo:

    int pthread_cancel(pthread_t thread);

  • Habilitar o inhabilitar la cancelación:

    int pthread_setcancelstate(int new_state,

    int *old_state);

    • PTHREAD_CANCEL_ENABLE o PTHREAD_CANCEL_DISABLE

  • Establecer el tipo de cancelación:

    int pthread_setcanceltype(int new_type,

    int *old_type);

    • PTHREAD_CANCEL_ASYNCHRONOUS o PTHREAD_CANCEL_DEFERRED

  • Verificar y terminar si se ha solicitado la cancelación:

    void pthread_testcancel(void);


Ejemplo14
Ejemplo

#include <pthread.h>

void *Hilo (void *arg) {

while(1) {

printf (“%s\n”, (char *)arg);

sleep(1); }

} /* Fin de Hilo */

main() {

pthread_t th1;

pthread_create (&th1, NULL, Hilo, “Hilo 1”);

sleep(5);

pthread_cancel(th1);

printf(“Envío cancel al Hilo 1 ...\n”);

sleep(5);

} /* Fin de main */


Terminaci n
Terminación

  • Se puede instalar manejadores de terminación de hilos

  • Cuando el hilo termina voluntariamente o por una cancelación, automáticamente se invoca a la función de terminación especificada

  • Esta posibilidad evita el problema de dejar al sistema en un estado inconsistente


Funciones asociadas9
Funciones asociadas

  • Para instalar un manejador de terminación:

    void pthread_cleanup_push(void *(*cleanup)(void *), void *arg);

  • Para eliminar el último manejador instalado:

    void pthread_cleanup_pop(int exec);

    • Si exec!=0, la función se elimina y se ejecuta



Planificaci n de threads
Planificación de threads

  • Existen las mismas políticas que para los procesos

  • Los atributos de planificación se pueden especificar al crear el hilo en el objeto de atributos

  • Se puede seleccionar entre dos ámbitos de planificación:

    • Ámbito de proceso: un planificador de segundo nivel planifica los hilos de cada proceso PTHREAD_SCOPE_PROCESS

    • Ámbito de sistema: los hilos se planifican como los procesos pesados PTHREAD_SCOPE_SYSTEM


Mbitos contentionscope
Ámbitos (contentionscope)

Hilos

Planificador

Sistema Operativo

Planificador


Herencia
Herencia

  • Si existe herencia no se hace caso del resto de los atributos de planificación

  • Valores:

    • PTHREAD_INHERIT_SCHED: hereda los atributos del padre

    • PTHREAD_EXPLICIT_SCHED: utiliza los del objeto attr


Funciones asociadas10
Funciones asociadas

  • Definición y obtención del ámbito de contención:

    int pthread_attr_setscope(pthread_attr_t *attr, int scope);

    int pthread_attr_getscope(const pthread_attr_t *attr, int *scope);

  • Definición y obtención de valores de herencia:

    int pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit);

    int pthread_attr_getinheritsched(const pthread_attr_t *attr, int *inherit);


Funciones asociadas11
Funciones asociadas

  • Definición y obtención de los valores de la política de planificación:

    int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy);

    int pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy);

  • Definición y obtención de la prioridad:

    int pthread_attr_setschedparam(pthread_attr_t *attr, const struct sched_param *param);

    int pthread_attr_getschedparam(const pthread_attr_t *attr, struct sched_param *param);


Cambio din mico de par metros
Cambio dinámico de parámetros

  • Se puede modificar dinámicamente la política de planificación y la prioridad:

    int pthread_setschedparam(pthread_t thread, int policy, const struct sched_param *param);

    int pthread_getschedparam(pthread_t thread, int *policy, struct sched_param *param);



Introducci n6
Introducción

  • Una señal es un mecanismo para avisar a los proceso de la llegada de un evento

    • División por cero

    • Desbordamiento

    • Expiración de alarmas

    • Llegada de un mensaje

    • etc.

  • Cada señal es identificada por un número

  • Cuando llega una señal, el proceso es interrumpido y se invoca a un manejador de señal


Se ales ordinarias
Señales ordinarias

Las señales no son fiables, se pueden perder si existen señales del mismo número pendientes

SIGILL Instrucción ilegal

SIGFPE Operación aritmética errónea

SIGSEGV Acceso a memoria erróneo

SIGINT Señal de atención interactiva (Ctrl-c)

SIGPIPE Escritura en una tubería sin lectores

SIGSTOP Detiene al proceso

SIGCONT Reanuda el proceso

SIGUSR1 Reservada para el usuario

SIGUSR2 Reservada para el usuario


Se ales de tiempo real
Señales de tiempo real

  • Las señales de tiempo real, si son soportadas, existen con números comprendidos entre SIGRTMIN y SIGRTMAX

  • Las señales de tiempo real son fiables y:

    • No se pierden nunca (se encolan)

    • Se aceptan en orden de prioridad (número)

    • Pueden transmitir un poco de información, un entero o un puntero

    • Existen como mínimo 8


Generaci n entrega y aceptaci n
Generación, entrega y aceptación

  • Un señal se genera:

    • Cuando se produce el evento asociado

  • Una señal se entrega

    • Cuando la señal causa al proceso la acción asociada

    • La acción se determina en recepción

  • Una señal se acepta:

    • Al seleccionarla

    • Para aceptar una señal esta debe estar enmascarada


Generaci n entrega y aceptaci n1
Generación, entrega y aceptación

  • Señal pendiente:

    • Estado entre su generación y su entrega o aceptación

    • Observable si la señal está enmascarada

    • Si se produce el mismo evento asociado a una señal pendiente:

      • Si es una señal no fiable, el evento se puede perder

      • Si es una señal fiable, y se ha especificado la acción SA_SIGINFO, la señal se encola

  • Cada hilo puede tener su máscara

  • La máscara es heredada y se puede modificar


Acciones asociadas a se ales
Acciones asociadas a señales

  • Antes de que llegue una señal el proceso puede prepararse para recibirla y actuar

  • El tratamiento de la señal puede implicar:

    • Ignorar la señal (SIG_IGN)

    • Dejar que el sistema la trate por defecto (SIG_DFL)

    • Manejarla con una función específica: cuando se entrega la señal se ejecuta el manejador indicado y se continúa la ejecución en el punto donde fuimos interrumpidos


Manejadores de se al
Manejadores de señal

  • POSIX define dos tipos de manejador:

    • Si se especifica SA_SIGINFO

      void manejador (int signo);

    • Si no se especifica SA_SIGINFO

      void manejador (int signo, siginfo_t *info,

      void *context);

  • La estructura siginfo_t mantiene, entre otras cosas, el número de señal (si_signo) y la causa (si_code)


Se ales en procesos multihilo
Señales en procesos multihilo

  • Las señales pueden enviarse a procesos a a hilos

    • Si el evento está asociado a un hilo, la señal es enviada al hilo correspondiente

    • Si el evento es asíncrono, se envía al proceso

    • Las señales asociadas a un PID se envían al proceso y las asociadas a un TID se envían a un hilo


Se ales en procesos multihilo1
Señales en procesos multihilo

  • Una señal asociada a un hilo:

    • Si no está bloqueada, se entrega

    • Si está bloqueada y la acción no es ignorar se queda pendiente hasta que es desbloqueada o aceptada con sigwait()

    • Si está bloqueada y la acción es ignorar: no está especificado


Se ales en procesos multihilo2
Señales en procesos multihilo

  • Una señal asociada a un proceso:

    • Si la acción no es ignorar, se envía a un único hilo que esté esperando con sigwait() o a un hilo que no tenga la señal bloqueada

    • Si no es entregada, la señal queda pendiente hasta que un hilo llama a sigwait(), un hilo desbloquea la señal o la acción asociada se pone en ignorar


Funciones de configuraci n
Funciones de configuración

  • Prototipos definidos en:

    #include <signal.h>

  • Funciones:

    int sigaddset(sigset_t *set, int sig);

    int sigdelset(sigset_t *set, int sig);

    int sigemptyset(sigset_t *set);

    int sigfillset(sigset_t *set);

    int sigismember(sigset_t *set, int sig);

  • Todas ellas permiten manipular la máscara de señales apuntada por set


Funciones de tratamiento
Funciones de tratamiento

  • Para examinar y cambiar la acción asociada a una señal:

    int sigaction (int signum,

    const struct sigaction *act,

    struct sigaction *oldact);

    • Si act=NULL, la acción no se modifica

    • Si oldact!=NULL la acción actual se devuelve en *oldact


Estructura sigaction
Estructura sigaction

struct sigaction {

void (*sa_handler)(int);

sigset_t sa_mask;

int sa_flags;

void (*sa_restorer)(void);

}

  • El primer campo es el puntero al manejador o también SIG_DFL o SIG_IGN

  • El segundo campo es la máscara de señales para cuando estamos tratando la actual


Estructura sigaction1
Estructura sigaction

  • El tercer campo puede valer:

    • SA_SIGINFO: La señal se encola y lleva información adicional (el manejador de señal es de tres argumentos)

    • SA_NOCLDSTOP: no generar SIGCHLD cuando un hijo se detiene

  • El cuarto campo es el puntero a la función que se ejecutará si esta definido el flag SA_SIGINFO


Bloqueo de se ales
Bloqueo de señales

  • Para examinar y cambiar las señales bloqueadas:

    int sigprocmask (int operation, cont sigset_t *set, sigset_t *oldset); /* un único hilo */

    int pthread_sigmask(int operation, const sigset_t *set, sigset_t *old_set);

    • operation indica el modo de operar:

      • SIG_BLOCK: añade señales bloqueadas

      • SIG_UBLOCK: elimina señales bloqueadas

      • SIG_SETMASK: modifica toda la mascara de señales

    • set: señales afectadas. Si vale NULL, no se cambia ninguna

    • oldset: si !=NULL, devuelve las señales bloqueadas anteriormente


Env o de se ales
Envío de señales

  • Para enviar señales a procesos:

    int kill (pid_t pit, int sig);

    int sigqueue (pid_t victim_id, int this_sig, union

    sigval extra_info);

  • Para enviar señales a hilos:

    int pthread_kill(pthread_t thread, int sig);


Aceptaci n de se ales
Aceptación de señales

  • Para examinar señales pendientes:

    int sigpending (sigset_t *set);

  • Para esperar a que se ejecute un manejador de señal:

    int pause(void);

    int sigsuspend (const sigset_t *mask);

    • sigsuspend() sustituye la máscara de señales con la apuntada por mask y espera la recepción de una de ellas. Al retornar se restaura la máscara original


Aceptaci n de se ales1
Aceptación de señales

  • Esperar a una señal bloqueada:

    int sigwait(const sigset_t *set, int *sig);

    int sigwaitinfo(const sigset_t *set, siginfo_t *value);

    int sigtimedwait(const sigset_t *set, siginfo_t *value, timespec_t *timeout);


Ejemplo15
Ejemplo

#include <signal.h>

#include <stdio.h>

void manejador (int senal) {

printf (“Recibida la señal ... \n”);

}

main() {

struct sigaction accion;

accion.sa_flags = 0;

accion.sa_handler = manejador;

sigemptyset (&accion.sa_mask);

sigaction (SIGUSR1, &accion, NULL);

while (1);

} /* Fin de main */



Mutex
Mutex

  • Es un objeto de sincronización que permite el acceso exclusivo a recursos

  • Operaciones:

    • P()

    • V()

  • Soportan herencia de prioridad


Objeto de atributos
Objeto de atributos

  • Atributos de inicio:

    • pshared: compartido o no entre procesos

      • PTHREAD_PROCESS_SHARED

      • PTHREAD_PROCESS_PRIVATE

    • protocol: protocolo utilizado

      • PTHREAD_PRIO_NONE: sin herencia

      • PTHREAD_PRIO_INHERIT: con herencia

      • PTHREAD_PRIO_PROTECT: protección de prioridad

    • prioceiling: techo de prioridad

  • Estos atributos se almacenan en el objeto de atributos


Funciones de manipulaci n
Funciones de manipulación

int pthread_mutexattr_init(pthread_mutexattr_t *attr);

int pthread_mutexattr_destroy(pthread_mutexattr_t *attr);

int pthread_mutexattr_setprotocol(pthread_mutexattr_t *attr, int protocol);

int pthread_mutexattr_getprotocol(const pthread_mutexattr_t *attr, int *protocol);

int pthread_mutexattr_setprioceiling (pthread_mutexattr_t *attr, int prioceiling);

int pthread_mutexattr_getprioceiling(const pthread_mutexattr_t *attr, int *prioceiling);


Manejo de mutex
Manejo de mutex

int pthread_mutex_init(pthread_mutex_t *mutex,

const pthread_mutexattr_t *attr);

int pthread_mutex_lock(pthread_mutex_t *mutex);

int pthread_mutex_trylock(pthread_mutex_t *mutex);

int pthread_mutex_unlock(pthread_mutex_t *mutex);

int pthread_mutex_destroy(pthread_mutex_t *mutex);


Cambio del techo de prioridad
Cambio del techo de prioridad

int pthread_mutex_setprioceiling(pthread_mutex_t *mutex, int prioceiling, int *old_ceiling);

int pthread_mutex_getprioceiling(const pthread_mutex_t *mutex, int *prioceiling);


Variables de condici n
Variables de condición

  • Es un objeto de sincronización que permite bloquear a un hilo hasta que otro decide reactivarlo

  • Operaciones:

    • Esperar una condición: un hilo se suspende hasta que otro señaliza la condición. En este punto se comprueba la condición y el proceso se repite si la condición es falsa

    • Señalizar una condición: se avisa a uno o más hilos suspendidos

    • broadcast: se reactivan todos los hilos suspendidos en la condición


Atributos
Atributos

  • pshared: indica si se puede compartir entre procesos

    • PTHREAD_PROCESS_SHARED

    • PTHREAD_PROCESS_PRIVATE

  • Funciones:

    int pthread_condattr_init(pthread_condattr_t *attr);

    int pthread_condattr_destroy(pthread_condattr_t *attr);


Funciones asociadas12
Funciones asociadas

int pthread_cond_init(pthread_cond_t *cond,

const pthread_condattr_t *attr);

int pthread_cond_signal(pthread_cond_t *cond);

int pthread_cond_broadcast(pthread_cond_t *cond);

int pthread_cond_wait(pthread_cond_t *cond,

pthread_mutex_t *mutex);

int pthread_cond_timedwait(pthread_cond_t *cond,

pthread_mutex_t *mutex, const struct timespec *abstime);


Referencias
Referencias

  • Michael González Harbour: POSIX de Tiempo Real. 1995. Curso de doctorado

  • Ismael Ripoll. POSIX 1003. Curso de doctorado

  • Juan Antonio de la Puente. Curso de doctorado

  • Programming for the Real World. POSIX.4. Bill o. Gallmeister. O´Reilly. 1995

  • Pthreads Programming. Bradford Nichols. O’Reilly. 1996


ad