La descarga está en progreso. Por favor, espere

La descarga está en progreso. Por favor, espere

Realizado por: Marina Ramos Carmen Camacho

Presentaciones similares


Presentación del tema: "Realizado por: Marina Ramos Carmen Camacho"— Transcripción de la presentación:

1 Realizado por: Marina Ramos Carmen Camacho
Hilos en Linux Realizado por: Marina Ramos Carmen Camacho

2 Historia Sistema Unix. Su desarrollo comenzó en 1991.
Estudiante finlandés, Linus Torvalds, escribió y bautizo a Linux. Un kernel pequeño, pero autocontenido, para el procesador Código fuente de Linux se ofreció gratuitamente en la Internet. Desde un kernel inicial que implementaba parcialmente un subconjunto de los servicios de sistema de Unix, el sistema Linux ha crecido hasta incluir gran parte de la funcionalidad de Unix.

3 Historia Es útil hacer la distinción entre el Kernel de Linux y el sistema Linux, el Kernel de Linux es una pieza de software completamente original desarrollada a partir de cero por la comunidad Linux; el sistema Linux, como lo conocemos hoy en día, incluye una multitud de componentes, algunos escritos a partir de cero, otros tomados a préstamo de otros proyectos de desarrollo o creados en colaboración con otros equipos de trabajo.

4 Sistema Linux Las principales bibliotecas del sistema de Linux se iniciaron en el proyecto GNU, pero la comunidad Linux dedico mucho esfuerzo en la mejora de dicha biblioteca para hacer frente a omisiones, deficiencias y errores. Otros componentes como el compilador C para GNU, gcc, ya tenían una calidad suficientemente elevados para usarse directamente en Linux.

5 Distribuciones de Linux
Red Hat y Debian son distribuciones particularmente populares de una compañía de soporte comercial de Linux y de la comunidad de Linux de software gratuito. Un gran esfuerzo de trabajo sobre Linux en Alemania ha dado como resultado varias distribuciones en idioma alemán, incluyendo versiones de SuSE. La variedad de distribuciones disponibles no prohíbe la compatibilidad entre dichas distribuciones. La mayoría de ellas utiliza, o por lo menos entiende, el formato de archivos de paquete RPM, y las aplicaciones comerciales distribuidas en este formato pueden instalarse y correrse en cualquier distribución que acepte archivos RPM.

6 Kernel en Linux Los kernels con un numero impar de versión menor como 1.1, 1.3 o 2.1 son kernels de desarrollo; los números pares de versión menor corresponden a kernels estables de producción.

7 Linux: Kernel Reentrante
Esto significa que mas de un proceso puede estar ejecutándose en modo kernel al mismo tiempo. Si ocurre una interrupción de hardware, un kernel reentrante es capaz de suspender el proceso actual, incluso si este proceso esta ejecutándose en modo kernel.

8 Interrupciones y excepciones
Una interrupción suele ser definida como un evento que altera la secuencia de instrucciones ejecutadas por un procesador. Suelen clasificarse en: Excepciones: producidas por la unidad de control de la CPU. Interrupciones: generadas por otros dispositivos de hardware.

9 Interrupciones Críticas: Acciones como confirmar la interrupción al PIC, reprogramar al dispositivo de hardware, acceder a estructuras de datos compartidas por el dispositivo y el procesador, etc. No Críticas: Acciones como leer a datos accedidos sólo desde el procesador (por ejemplo, leer el “scan code” después que una tecla fue presionada). Diferibles: Acciones como copiar el contenido de un buffer en el espacio de algún proceso. Son realizadas desde funciones separadas.

10 Procesos en Linux En el código de Linux los procesos se conocen como tareas. Linux utiliza procesos ligeros para ofrecer un proceso optimo a las aplicaciones multi-hilos. Cada proceso ligero es planificado de manera independiente por el núcleo de forma que si, por ejemplo, uno de los dos LWP (Nivel intermedio entre los hilos a nivel kernel y los hilos a nivel usuario) se queda bloqueado en una llamada al sistema el otro puede progresar en su ejecución.

11 Creación de un Proceso:
En UNIX la creación de un proceso consiste en dos pasos: Reserva de espacio de direcciones (fork()). Carga de un programa ejecutable en ese espacio de direcciones (exec(..)). En Linux, la llamada al sistema fork() utiliza la técnica copy-on-write: En lugar de duplicar el espacio de direcciones, el proceso padre e hijo lo comparten. Cuando el hijo realiza una escritura (ej: modifica una variable) el Kernel sólo copia la página de memoria en la que se encuentra definida esa variable. Único overhead incurrido por fork(): copia de tablas de páginas del padre y creación del descriptor del proceso.

12 Creación de un Proceso (cont):
Linux implementa la función fork() mediante la llamada al sistema clone(). clone() toma una serie de flags que indican qué recursos deben compartir el proceso padre e hijo. Las funciones fork(), vfork() y __clone() invocan a la llamada al sistema clone(). A su vez, clone() acaba invocando a la función do_fork() definida en el fichero kernel/fork.c.

13 Creación de un Proceso (cont):
do_fork() lleva a cabo las siguientes operaciones: 1. Crea una nueva pila de Kernel, una estructura thread_info y una estructura task_struct (hasta este punto ambas estructuras contienen el mismo valor). 2. Verifica que el nuevo proceso no implica superar el límite de recursos del número máximo de procesos del usuario actual. 3. Inicializan varios campos del descriptor del proceso hijo diferenciándose así de su padre. 4. Se estable como estado del proceso hijo TASK_UNINTERRUPTIBLE. 5. Se invoca a la función get_pid() para obtener un PID. 6. El cuanto de tiempo restante del proceso padre es repartido entre los dos. 7. Se retorna al invocador un puntero al nuevo proceso hijo.

14 Procesos e Hilos Los procesos representan la ejecución de programas individuales, en tanto que los hilos representan contextos de ejecución concurrentes y distintos dentro de un solo proceso que corre con un solo programa. Los procesos tienen sus propios espacios de dirección, mientras que los hilos solo tienen un espacio de dirección en el que todos están corriendo.

15 Implementación de hilos
En el núcleo de Linux NO existe el concepto de hilo. Linux implementa todos los hilos como procesos estándar. Linux considera un hilo como un proceso que comparte ciertos recursos con otros procesos. Cada hilo tiene su propio descriptor de proceso y aparece para el núcleo como un proceso normal más. Los hilos se crean como tareas normales con la excepción de que en la llamada al sistema clone() se pasan los flags correspondientes a los recursos compartidos: clone(CLONE_VM |CLONE_FS |CLONE_FILES |CLONE_SIGHAND,0);

16 Hilos El código, los datos y los recursos son poseídos por otra entidad conocida como tarea (task). Una tarea sin hilos no tiene capacidad de ejecución, sólo “posee” recursos. Cada hilo sólo puede pertenecer a una tarea. Los threads son muy adecuadas para sistemas distribuidos y sistemas multiprocesador (cada hilo se puede ejecutar en un procesador).

17 Hilos (cont.) Un proceso tradicional (proceso pesado) se compone de una tarea con un hilo de ejecución. La conmutación de un hilo a otro en la misma tarea requiere un coste mínimo ya que solo es necesario salvar los registros y conmutar la pila. Los hilos pueden ser implementados a nivel de usuario o como llamadas al sistema.

18 Pthreads La librería de pthreads es una librería que cumple los estándares POSIX y que nos permite trabajar con distintos hilos de ejecución (threads) al mismo tiempo. Los threads comparten totalmente la memoria entre ellos. Para crear threads se usan las funciones de la librería pthread o de cualquier otra que soporte threads mientras que para crear procesos usaremos la llamada al sistema fork(), que se encuentra en todos los sistemas Unix.

19 Creación y Manipulación de Threads
Para crear un thread nos valdremos de la función pthread_create de la librería y de la estructura de datos pthread_t que identifica cada thread diferenciándolo de los demás y que contiene todos sus datos. Ejemplo

20 Funciones Básicas int  pthread_create(pthread_t  *  thread, pthread_attr_t *attr, void * (*start_routine)(void *), void *arg) int pthread_join(pthread_t th, void **thread_return) int pthread_detach(pthread_t th) void pthread_exit(void *retval)

21 Otras Funciones Útiles
pthread_t pthread_self(void) int pthread_kill(pthread_t thread, int signo) int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr) int pthread_mutex_lock(pthread_mutex_t *mutex) int pthread_mutex_unlock(pthread_mutex_t *mutex) int pthread_mutex_destroy(pthread_mutex_t *mutex) pthread_mutexattr_settype(&mutex_attr, tipo); int pthread_mutex_trylock(pthread_mutex_t *mutex);

22 Funciones Avanzadas int pthread_attr_init(pthread_attr_t *attr); int pthread_attr_destroy(pthread_attr_t *attr); int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate); int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate); int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy); int pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy); 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);

23 Semáforos A veces es necesario que dos o más procesos o hilos accedan a un recurso común. El problema es que si lo hacen simultáneamente y de forma incontrolada, pueden "machacar" el uno la operación del otro . Para evitar este problema, están los semáforos. Un semáforo da acceso al recurso a uno de los procesos y se lo niega a los demás mientras el primero no termine. El funcionamiento del semáforo es como el de una variable contador.

24 Pasos para utilizar los semáforos en un programa: :
Obtener una clave de semáforo. Para ello se utiliza la función key_t  ftok(char *, int). Obtener un array de semáforos. La función int semget (key_t, int, int). Uno de los procesos debe inicializar el semáforo. La función a utilizar es int semctl (int, int, int, int).

25 Continuación Ya está todo preparado, ahora sólo queda usar los semáforos. El proceso que quiera acceder a un recurso común debe primero decrementar el semáforo. Para ello utilizará la función int semop (int, strcut sembuf *, size_t). Cuando el proceso termine de usar el recurso común, debe incrementar el semáforo. La función a utlizar es la misma, pero poniendo 1 en el campo sem_op de la estructura strcut sembuf.

26 Continuación Para mayor información sobre semáforos consultar:

27 Mutex en Linux En primer lugar, los mutexes se usan para serializar el acceso a *datos compartidos*. No deben usarse para datos que no se van a compartir, y tampoco deben usarse si la lógica interna de nuestro programa asegura que sólo un hilo está accediendo a una estructura concreta de datos a la vez. En segundo lugar, si se están usando datos compartidos, hay que usar los mutexes tanto para la lectura como para la escritura. Hay que subordinar las secciones de lectura y escritura a pthread_mutex_lock() y pthread_mutex_unlock(), o usarlas cada vez que un programa invariable está causando errores temporalmente.

28 ¿Por qué no evitar los mutex por completo? .
Mutex en Linux Ilustración 1.1: Para disfrutarlo, cuatro znurts re-habilitan una escena de llamadas pthread_mutex_lock() recientes ¿Por qué no evitar los mutex por completo? . Ejemplo

29 Bibliografía atc1.aut.uah.es/~edssoo/Transparencias/3.Procesos%20e%20hilos.pps


Descargar ppt "Realizado por: Marina Ramos Carmen Camacho"

Presentaciones similares


Anuncios Google