Planificador

1,193 views

Published on

pascual cano

Published in: Technology, News & Politics
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,193
On SlideShare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
0
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

Planificador

  1. 1. <ul><li>Diseño de Sistemas Operativos </li></ul><ul><li>Planificador de Procesos </li></ul><ul><li>(Scheduler) </li></ul>Abián Izquierdo Montesdeoca Eduardo J. Delgado Mateo
  2. 2. Introducción a los procesos <ul><li>Un programa es un conjunto de instrucciones de código máquina y datos guardados en disco en una imagen ejecutable y como tal, es una entidad pasiva. </li></ul><ul><li>Un proceso es un programa en ejecución, incluyendo su contador de programa y los registros de la CPU así como la pila para datos temporales y parámetros de las rutinas, direcciones de retorno y variables salvadas. </li></ul>
  3. 3. Introducción a los procesos <ul><li>Un proceso consume muchos recursos del sistema, los más importantes son: </li></ul><ul><ul><li>CPU, para ejecutar sus instrucciones. </li></ul></ul><ul><ul><li>Memoria física, para almacenar al propio proceso y sus datos. </li></ul></ul><ul><ul><li>Ficheros y otros dispositivos del sistema. </li></ul></ul><ul><li>El recurso más preciado en el sistema es la CPU y normalmente sólo hay una. </li></ul>
  4. 4. Introducción a los procesos <ul><li>Un sistema multiproceso mantiene muchos procesos en memoria simultáneamente y uno se ejecuta hasta que tenga que esperar, normalmente por algún recurso del sistema. </li></ul><ul><li>Estos procesos son tareas independientes. Si un proceso se desploma, no hará que otros procesos en el sistema fallen también. </li></ul><ul><li>Cada proceso se ejecuta en su propio espacio de memoria virtual sin interaccionar con otros procesos, excepto a través de mecanismos del núcleo. </li></ul>
  5. 5. Introducción a los procesos <ul><li>El objetivo es tener un proceso ejecutándose en cada CPU del sistema en todo momento. </li></ul><ul><li>Cuando un proceso tiene que esperar, el sistema operativo le quita la CPU a ese proceso y se la da a otro proceso que se la merezca más. </li></ul><ul><li>De esto se encarga el planificador . </li></ul>
  6. 6. Los procesos de Linux <ul><li>LINUX es un sistema multiproceso. </li></ul><ul><li>Debe llevar cuentas de los procesos en sí y de los recursos del sistema que está usando, de manera que pueda gestionarlos justamente. </li></ul><ul><li>Usa varias estrategias de organización del tiempo de la CPU para asegurar un reparto justo. </li></ul><ul><li>LINUX soporta procesos normales y de tiempo real , los cuales deben reaccionar muy rápidamente a sucesos y reciben un trato diferente del planificador. </li></ul>
  7. 7. Los procesos de Linux <ul><li>Linux representa cada proceso por una estructura de datos task_struct . </li></ul><ul><li>El vector task es una lista de punteros a estructuras task_struct en el sistema. </li></ul><ul><li>Para encontrar fácilmente el proceso en ejecución, hay un puntero ( current ) que apunta a este proceso. </li></ul>
  8. 8. Los procesos de Linux <ul><li>Los campos de la estructura task_struct se pueden dividir en áreas funcionales: </li></ul><ul><ul><li>Información de Estado : a medida que un proceso se ejecuta, su estado cambia según las circunstancias. Estos pueden ser running, waiting, stopped y zombie. </li></ul></ul><ul><ul><li>Información de la Planificación de Tiempo de la CPU: necesaria para decidir qué proceso se ejecuta a continuación. </li></ul></ul><ul><ul><li>Identificadores: de proceso, usuario y grupo. </li></ul></ul>
  9. 9. Los procesos de Linux <ul><ul><li>Enlaces: punteros a los procesos padre, hermanos e hijos. </li></ul></ul><ul><ul><li>Tiempos y Temporizadores : hora de creación del proceso, consumo de CPU y temporizadores. </li></ul></ul><ul><ul><li>Sistema de Ficheros : punteros a los descriptores de cada fichero abierto por el proceso. </li></ul></ul><ul><ul><li>Contexto Específico del Procesador : todos los procesos utilizan los registros, la pila, etc, pero cada uno con valores propios, su “contexto” . </li></ul></ul>
  10. 10. Planificación de procesos <ul><li>Cada proceso decide dejar la CPU que está usando cuando tiene que esperar algún suceso en el sistema: el proceso será suspendido y se seleccionará a otro para ejecutarse. </li></ul><ul><li>El planificador tiene que elegir el proceso que más merece ejecutarse entre todos los procesos que se pueden ejecutar en el sistema. </li></ul><ul><li>Cuando se ha elegido un nuevo proceso para ejecutar, el planificador salva el contexto del proceso en curso y luego restaura el estado del nuevo proceso y le da control del sistema. </li></ul>
  11. 11. Planificación de procesos <ul><li>La información almacenada por el sistema para realizar la planificación de procesos es la siguiente: </li></ul><ul><ul><li>policy: política de planificación que se aplicará a este proceso. </li></ul></ul><ul><ul><li>priority : prioridad estática del proceso. </li></ul></ul><ul><ul><li>rt_priority: prioridad de tiempo real. </li></ul></ul><ul><ul><li>counter : cuanto de tiempo que falta por consumir. </li></ul></ul>
  12. 12. Planificación de procesos <ul><li>En Linux hay dos tipos de procesos, normales y de tiempo real: si hay un proceso de tiempo real preparado, siempre se ejecutará primero. </li></ul><ul><li>Los procesos normales ( SCHED_OTHER ) se planifican en base al valor actual de su campo counter : en cada instante se ejecuta el que mayor valor de counter tiene. </li></ul><ul><li>Los procesos de tiempo real pueden tener dos tipos de políticas: FIFO y Round Robin. </li></ul>
  13. 13. Planificación de procesos <ul><li>SCHED_RR: cada proceso de tiempo real se ejecuta por turnos. Cuando a un proceso se le acaba su rodaja de tiempo, abandona el procesador. </li></ul><ul><li>SCHED_FIFO: cada proceso se ejecuta en el orden que están en la cola de ejecución. Y sin tener en cuenta su rodaja de tiempo se ejecutará hasta que: </li></ul><ul><ul><li>Se bloquee al necesitar esperar por la finalización de una operación de E/S. </li></ul></ul><ul><ul><li>El procesador sea solicitado por otro proceso en tiempo real con una prioridad mayor. </li></ul></ul><ul><ul><li>El proceso ceda voluntariamente el procesador utilizando la primitiva sched_yield. </li></ul></ul>
  14. 14. Planificación de procesos <ul><li>La estructura de datos del núcleo que representa un proceso es struct task_struct definida en el fichero <linux/shed.h> . </li></ul><ul><li>Linux utiliza un tabla de procesos compuesta por este tipo de estructuras llamada task : </li></ul><ul><li>16517 extern struct task_struct *task[NR_TASKS]; </li></ul><ul><li>Cada proceso tiene asignado un identificador mediante el cual se obtiene su entrada correspondiente en la tabla. </li></ul>
  15. 15. Tabla de procesos: ( 1 ) <ul><li>» struct_task struct * next_task Puntero al siguiente proceso en la lista. </li></ul><ul><li>» struct_task struct * prev_task Puntero al anterior proceso en la lista. </li></ul><ul><li>» struct_task struct * next_run Puntero al siguiente proceso en la lista de procesos preparados. </li></ul><ul><li>» struct_task struct * prev_run Puntero al anterior proceso en la lista de procesos preparados. </li></ul><ul><li>» struct_task struct * p_pptr, p_opptr, Punteros a los procesos padre, padre original, </li></ul><ul><li>p_ysptr, p_cptr, p_osptr hermano mas reciente, hijo más reciente y hermano más antiguo. </li></ul><ul><li>» int pid Identificador del proceso. </li></ul><ul><li>» unsigned short uid, euid, gid, egid, … Identificadores de usuario (real y efectivo), grupo, ... </li></ul><ul><li>» volatile long state Estado del proceso. </li></ul><ul><li>» long counter Número de ciclos de reloj durante los que está autorizado a ejecutarse. </li></ul><ul><li>» unsigned shorttimeout Máximo tiempo de espera en estado de Espera </li></ul>
  16. 16. Tabla de procesos: (2) <ul><li>» unsigned shortpolicy Política de planificación asociada al proceso. </li></ul><ul><li>» long priority Prioridad estática del proceso. </li></ul><ul><li>» unsigned short rt_priority Prioridad estática para procesos en tiempo real. </li></ul><ul><li>» unsigned long signal Señales en espera. </li></ul><ul><li>» struct signal_struct * sig Puntero a los descriptores de las acciones asociadas a las señales. </li></ul><ul><li>» unsigned long blocked Señales ocultas. </li></ul><ul><li>» int exit signal Código de la señal a enviar al padre al finalizar. </li></ul><ul><li>» int exit code Código a devolver al padre: bits(0..7): número de la señal que provocó el final del proceso bits(8..15): código devuelto por la primitiva _exit. </li></ul><ul><li>» struct wait_queue * wait_chldexit Variable utilizada para esperar la finalización de un proceso hijo. </li></ul><ul><li>» int errno Variable global donde las llamadas al sistema colocan el código de error que generan. </li></ul>
  17. 17. Tabla de procesos: (3) <ul><li>» long utime, stime, cutime, cstime Tiempos consumidos por el proceso y por sus hijos en modo usuario y modo núcleo. </li></ul><ul><li>» int:1 dumpable Indica si se debe crear un fichero CORE en caso de error fatal. </li></ul><ul><li>» int:1 swappable Indica si el proceso se puede guardar en memoria secundaria. </li></ul><ul><li>» long[8] debugreg Copia de los registros hardware para depuración </li></ul><ul><li>» struct desc_struct * ldt Puntero a la tabla de segmentos local del proceso </li></ul><ul><li>» struct thread_struct * tss Puntero a una estructura donde se guarda el valor de los registros del procesador. </li></ul><ul><li>» struct mm_struct * mm Información de control para la gestión de la memoria. </li></ul><ul><li>» struct files_struct * files Puntero a los descriptores de ficheros abiertos por el proceso. </li></ul><ul><li>» struct fs_struct * fs Información de control para el acceso a ficheros. </li></ul><ul><li>» struct tty_struct * tty Puntero al terminal asociado al proceso. </li></ul>
  18. 18. Los procesos de Linux <ul><li>La lista tarray_freelist , mantiene una lista de las posiciones libres en el vector task : </li></ul><ul><li>16519 extern struct task_struct ** tarray_freelist; </li></ul><ul><li>El array pidhash ayuda a mapear PIDs a punteros a estructuras del tipo struct task_struct : </li></ul><ul><li>16546 extern struct task_struct * pidhash[PIDHASH_SZ]; </li></ul>
  19. 19. Los procesos de Linux <ul><li>Las tareas forman una lista circular, doblemente encadenada llamada lista de tareas , utilizando los campos next_task y prev_task de la estructura. </li></ul><ul><li>Esta lista se utiliza para recorrer rápidamente todas las tareas actuales en el sistema evitándonos los slots vacíos del vector task . </li></ul><ul><li>Linux proporciona la siguiente macro para realizar el recorrido de la lista: </li></ul><ul><li>16898 #define for_each_task(p) </li></ul><ul><li>16899 for(p=&init_task; (p = p->next_task) != &init_task;) </li></ul>
  20. 20. Los procesos de Linux <ul><li>Linux guarda otra lista circular doblemente encadenada de tareas llamada run_queue, utilizando los campos prev_run y next_run . </li></ul><ul><li>Las tareas se añaden y eliminan de la cola usando las funciones add_to_runqueue y del_from_runqueue definidas en <linux/shed.c> . </li></ul><ul><li>Si es necesario mover procesos entre el inicio y el final de la cola, se usan las funciones move_first_runqueue y move_last_runqueue. </li></ul><ul><li>Se utiliza init_task para indicar el comienzo y final de las listas. </li></ul>
  21. 21. Los procesos de Linux <ul><li>Algunas líneas interesantes del fichero <linux/shed.h> son las siguientes: </li></ul><ul><ul><ul><li>16177 extern int nr_running, nr_tasks; </li></ul></ul></ul><ul><ul><ul><li>16178 extern int last_pid; </li></ul></ul></ul><ul><ul><ul><li>16188 #define TASK_RUNNING 0 </li></ul></ul></ul><ul><ul><ul><li>16189 #define TASK_INTERRUPTIBLE 1 </li></ul></ul></ul><ul><ul><ul><li>16190 #define TASK_UNINTERRUPTIBLE 2 </li></ul></ul></ul><ul><ul><ul><li>16191 #define TASK_ZOMBIE 4 </li></ul></ul></ul><ul><ul><ul><li>16192 #define TASK_STOPPED 8 </li></ul></ul></ul><ul><ul><ul><li>16193 #define TASK_SWAPPING 16 </li></ul></ul></ul><ul><ul><ul><li>16195 /* Scheduling policies */ </li></ul></ul></ul><ul><ul><ul><li>16196 #define SCHED_OTHER 0 </li></ul></ul></ul><ul><ul><ul><li>16197 #define SCHED_FIFO 1 </li></ul></ul></ul><ul><ul><ul><li>16198 #define SCHED_RR 2 </li></ul></ul></ul><ul><ul><ul><li>16200 /* This is an additional bit set when we want to yield </li></ul></ul></ul><ul><ul><ul><li>16201 * the CPU for one re-schedule.. */ </li></ul></ul></ul><ul><ul><ul><li>16202 #define SCHED_YIELD 0x10 </li></ul></ul></ul>
  22. 22. Planificación en Linux: Prioridades <ul><li>Cada proceso tiene una prioridad dada por un entero del 1 al 40, almacenado en el campo priority. </li></ul><ul><li>Los procesos en tiempo real además usan el campo “rt_priority”, que tiene un rango entre 0 y 99 (un 0 significa que el proceso no es un proceso de tiempo real). </li></ul><ul><li>Actualmente las funciones que controlan la prioridad son sys_set_priority y sys_nice , aunque esta última está obsoleta. </li></ul>
  23. 23. Planificación en Linux: Prioridades <ul><li>Tanto las tareas normales como las tareas en tiempo real usan el campo counter para estimar las prioridades. </li></ul><ul><li>Ambos tipos de procesos usan el campo counter para rellenar su cuanto de tiempo restante. </li></ul><ul><li>rt_priority se usa sólo para ordenar los procesos en tiempo real por prioridad. </li></ul><ul><li>Las funciones sched_setscheduler y sched_setparam permiten cambiar la politica de planificación de un proceso. </li></ul>
  24. 24. Función Schedule <ul><li>26686 asmlinkage void schedule(void) </li></ul><ul><li>26687 { </li></ul><ul><li>26688 struct schedule_data * sched_data; </li></ul><ul><li>26689 struct task_struct * prev, * next; </li></ul><ul><li>26691 </li></ul><ul><li>26692 /* prev = proceso actual */ </li></ul><ul><li>26694 prev = current; </li></ul><ul><li>26712 /* move an exhausted RR process to be last.. */ </li></ul><ul><li>26713 prev->need_resched = 0; </li></ul><ul><li>26714 /* Si counter==0 y es política Round Robin se </li></ul><ul><li>inicia su counter y se pasa al final de la cola */ </li></ul><ul><li>26715 if (!prev->counter && prev->policy == SCHED_RR){ </li></ul><ul><li>26716 prev->counter = prev->priority; </li></ul><ul><li>26717 move_last_runqueue(prev); </li></ul><ul><li>26718 } </li></ul>
  25. 25. Función Schedule <ul><li>/* Se eliminan de la cola los procesos que no estén en estado de </li></ul><ul><li>preparado. Si el proceso es interrumpible y está esperando una señal </li></ul><ul><li>se pone a preparado*/ </li></ul><ul><li>26720 switch (prev->state) { </li></ul><ul><li>26721 case TASK_INTERRUPTIBLE: </li></ul><ul><li>26722 if (signal_pending(prev)) { </li></ul><ul><li>26723 prev->state = TASK_RUNNING; </li></ul><ul><li>26724 break; </li></ul><ul><li>26725 } </li></ul><ul><li>26726 default: </li></ul><ul><li>26727 del_from_runqueue(prev); </li></ul><ul><li>26728 case TASK_RUNNING: </li></ul><ul><li>26729 } </li></ul>
  26. 26. Función Schedule <ul><li>/* Nos recorremos la lista de procesos preparados buscando el mejor </li></ul><ul><li>de todos para seleecionarlo */ </li></ul><ul><li>26733 /* this is the scheduler proper: */ </li></ul><ul><li>26734 { </li></ul><ul><li>26735 struct task_struct * p = init_task.next_run; </li></ul><ul><li>26736 int c = -1000; </li></ul><ul><li>26757 while (p != &init_task) { </li></ul><ul><li>26758 if (can_schedule(p)) { </li></ul><ul><li>26759 int weight = goodness(p, prev, this_cpu); </li></ul><ul><li>26760 if (weight > c) </li></ul><ul><li>26761 c = weight, next = p; </li></ul><ul><li>26762 } </li></ul><ul><li>26763 p = p->next_run; </li></ul><ul><li>26764 } </li></ul>
  27. 27. Función Schedule <ul><li>26766 /* Si todos los contadores == 0 se recalculan los </li></ul><ul><li>contadores de todos los procesos*/ </li></ul><ul><li>26767 if (!c) { </li></ul><ul><li>26768 struct task_struct *p; </li></ul><ul><li>26770 for_each_task(p) </li></ul><ul><li>26771 p->counter = p->priority; </li></ul><ul><li>26773 } </li></ul><ul><li>26774 } </li></ul><ul><li>26775 /* Si el proceso elegido es otro del actual-> CC */ </li></ul><ul><li>26801 if (prev != next) { </li></ul><ul><li>26804 /* Se incrementa el número de cambios de cont. */ </li></ul><ul><li>26805 kstat.context_swtch++; </li></ul><ul><li>26808 /* Se hace el cambio de contexto */ </li></ul><ul><li>26807 switch_to(prev,next); </li></ul><ul><li>26810 } </li></ul><ul><li>26813 return; </li></ul><ul><li>26818 } </li></ul>
  28. 28. Macro switch_to <ul><li>/* Se guardan en la pila los registros esi, edi y ebp */ </li></ul><ul><li>12939 #define switch_to (prev,next) do { </li></ul><ul><li>12940 unsigned long eax, edx, ecx; </li></ul><ul><li>12941 asm volatile(&quot;pushl %%ebx &quot; </li></ul><ul><li>12942 &quot;pushl %%esi &quot; </li></ul><ul><li>12943 &quot;pushl %%edi &quot; </li></ul><ul><li> &quot;pushl %%ebp &quot; </li></ul><ul><li>/* Se guarda el puntero de pila en la TSS del proceso*/ </li></ul><ul><li> &quot;movl %%esp,%0 &quot; /* save ESP */ </li></ul><ul><li>/* Se restaura el nuevo puntero de pila */ </li></ul><ul><li> &quot;movl %5,%%esp &quot; /* restore ESP */ </li></ul><ul><li>/* Se guarda la dirección de la etiqueta 1 en el contador de programa </li></ul><ul><li>del proceso (para luego retornar ahí */ </li></ul><ul><li>12947 &quot;movl $1f,%1 &quot; /* save EIP */ </li></ul>
  29. 29. Macro switch_to <ul><li>/* Se pone en la pila el contador de programa del nuevo proceso </li></ul><ul><li>(nuevo proceso que va a tomar la CPU) para luego hacer un pop y </li></ul><ul><li>comenzar */ </li></ul><ul><li>12948 &quot;pushl %6 &quot; /* restore EIP */ </li></ul><ul><li>/* Se guardan y actualizan los registros de segmento y las tablas de </li></ul><ul><li>paginas */ </li></ul><ul><li>12949 &quot;jmp __switch_to &quot; </li></ul><ul><li>/* Dirección del salto para un nuevo proceso */ </li></ul><ul><li>12950 &quot;1: &quot; </li></ul><ul><li>/*Se restaurán los registros restantes del nuevo proceso*/ </li></ul><ul><li>12951 &quot;popl %%ebp &quot; </li></ul><ul><li>12952 &quot;popl %%edi &quot; </li></ul><ul><li>12953 &quot;popl %%esi &quot; </li></ul><ul><li>12954 &quot;popl %%ebx&quot; </li></ul><ul><li>12959 } while (0) </li></ul>
  30. 30. Función goodness <ul><li>/*evalúa la prioridad de los candidatos a ser ejecutados a </li></ul><ul><li>continuación*/ </li></ul><ul><li>26388 static inline int goodness(struct task_struct * p, </li></ul><ul><li>26389 struct task_struct * prev, int this_cpu) </li></ul><ul><li>26390 { </li></ul><ul><li>26391 int policy = p->policy; </li></ul><ul><li>26392 int weight; </li></ul><ul><li>26393 /* Se reinicia el flag SCHED_YIELD */ </li></ul><ul><li>26394 if (policy & SCHED_YIELD) { </li></ul><ul><li>26395 p->policy = policy & ~SCHED_YIELD; </li></ul><ul><li>26396 return 0; </li></ul><ul><li>26397 } </li></ul>
  31. 31. Función goodness <ul><li>/* Si es un proceso de tiempo real se le aumenta su goodness en 1000 </li></ul><ul><li>para darle prioridad*/ </li></ul><ul><li>26402 if (policy != SCHED_OTHER) </li></ul><ul><li>26403 return 1000 + p->rt_priority; </li></ul><ul><li>26411 weight = p->counter; </li></ul><ul><li>/* Si el proceso comparte zonas de memoria con el anterior ejecutado </li></ul><ul><li>se aumenta su goodness. */ </li></ul><ul><li>26412 if (weight) { </li></ul><ul><li>26423 if (p->mm == prev->mm) </li></ul><ul><li>26424 weight += 1; </li></ul><ul><li>26425 weight += p->priority; </li></ul><ul><li>26426 } </li></ul><ul><li>26427 </li></ul><ul><li>26428 return weight; </li></ul><ul><li>26429 } </li></ul>
  32. 32. Otras funciones <ul><li>Existen un conjunto de funciones que manipulan procesos dentro de la cola de ejecución. Algunas de estas funciones son las siguientes: </li></ul><ul><ul><li>move_first_runqueue : mueve el proceso pasado por parámetro al principio de la cola de ejecución </li></ul></ul><ul><ul><li>move_last_runqueue : igual pero al final de la cola. </li></ul></ul><ul><ul><li>add_to_runqueue : añade un proceso al comienzo de la cola de ejecución </li></ul></ul><ul><ul><li>del_from_runqueue : </li></ul></ul>
  33. 33. Otras funciones <ul><li>/* Devuelve verdadero si el proceso tiene una señal pendiente </li></ul><ul><li>observando el campo sigpending de la estructura task_struct */ </li></ul><ul><li>16644 extern inline int signal_pending(struct task_struct * p) </li></ul><ul><li>16645 { </li></ul><ul><li>16646 return (p->sigpending != 0); </li></ul><ul><li>16647 } </li></ul>
  34. 34. Otras funciones <ul><li>/*Esta función modifica el nivel de prioridad de un proceso*/ </li></ul><ul><li>/* who: Identificador </li></ul><ul><li>which: Tipo de identificador: un proceso, un grupo de </li></ul><ul><li>procesos o todos los procesos de un usuario </li></ul><ul><li>niceval: Incremento de la prioridad (-20..19) </li></ul><ul><li>*/ </li></ul><ul><li>29213 asmlinkage int sys_setpriority(int which, int who,int niceval) </li></ul><ul><li>29214 </li></ul><ul><li>29215 { </li></ul><ul><li>29216 struct task_struct *p; </li></ul><ul><li>29217 unsigned int priority; </li></ul><ul><li>29218 int error; </li></ul><ul><li>29219 </li></ul>
  35. 35. Otras funciones <ul><li>/* Comprueba que es un tipo de identificador válido*/ </li></ul><ul><li>29220 if (which > 2 || which < 0) </li></ul><ul><li>29221 return -EINVAL; </li></ul><ul><li>29225 error = ESRCH; </li></ul><ul><li>/* Codigo reescrito por claridad. Se normaliza niceval entre 1 y 40*/ </li></ul><ul><li>if (niceval < -19) </li></ul><ul><li>priority = 40; </li></ul><ul><li>else </li></ul><ul><li>if (niceval > 19) </li></ul><ul><li> priority = 1; </li></ul><ul><li>else </li></ul><ul><li> priority = 20 – niceval; </li></ul><ul><li>/* Codigo reescrito por claridad */ </li></ul>
  36. 36. Otras funciones <ul><li>/* Se busca en las tareas del sistema cuales satisfacen las condiciones </li></ul><ul><li>“ who” y “which” y modifica sus prioridades si se tienen los permisos correspondientes.*/ </li></ul><ul><li>29240 </li></ul><ul><li>29241 for_each_task(p) { </li></ul><ul><li>29242 if (!proc_sel(p, which, who)) </li></ul><ul><li>29243 continue; </li></ul><ul><li>/* Se miran los permisos */ </li></ul><ul><li>29254 p->priority = priority; </li></ul><ul><li>29255 } </li></ul><ul><li>29258 return -error; </li></ul><ul><li>29259 } </li></ul><ul><li>/*Esta función devuelve la mayor de las prioridades de los procesos. </li></ul><ul><li>Es analoga a la anterior.*/ </li></ul><ul><li>29265 asmlinkage int sys_getpriority(int which, int who) </li></ul>
  37. 37. Otras funciones <ul><li>/*Esta función permite cambiar la política de planificación y/o </li></ul><ul><li>parámetros de la misma.*/ </li></ul><ul><li>27618 static int setscheduler(pid_t pid, int policy, </li></ul><ul><li>27619 struct sched_param *param) </li></ul><ul><li>27620 { </li></ul><ul><li>pid: el proceso objetivo, 0 significa proceso actual policy: la nueva política de planificación </li></ul><ul><li>param: un struct que contiene información adicional (el </li></ul><ul><li>nuevo valor para rt_priority). */ </li></ul><ul><li>27621 struct sched_param lp; </li></ul><ul><li>27622 struct task_struct *p; </li></ul>
  38. 38. Otras funciones <ul><li>/* Se copian los parametros de la zona de usuario */ </li></ul><ul><li>27630 copy_from_user(&lp, param, </li></ul><ul><li>27631 sizeof(struct sched_param))) </li></ul><ul><li>/* Se buca el proceso a modificar */ </li></ul><ul><li>27639 p = find_process_by_pid(pid); </li></ul><ul><li>/* ¿Se deja la misma política o se debe modificar? */ </li></ul><ul><li>27645 if (policy < 0) </li></ul><ul><li>27646 policy = p->policy; </li></ul><ul><li>/* Se comprueba que el proceso tiene permisos para cambiar su </li></ul><ul><li>politica de planificación */ </li></ul><ul><li>/* Se actualizan los campos */ </li></ul><ul><li>27672 p->policy = policy; </li></ul><ul><li>27673 p->rt_priority = lp.sched_priority; </li></ul>
  39. 39. Otras funciones <ul><li>/* Si es un proceso preparado se mueve al principio */ </li></ul><ul><li>27674 if (p->next_run) </li></ul><ul><li>27675 move_first_runqueue(p); </li></ul><ul><li>/* Se indica que se ha de replanificar */ </li></ul><ul><li>current->need_resched = 1; </li></ul><ul><li>27685 return retval; </li></ul><ul><li>27686 } </li></ul>
  40. 40. Otras funciones <ul><li>/* Esta función comprueba si el proceso pasado por parámetro es más </li></ul><ul><li>prioritario que el actual. Si es así habrá que replanificar el acceso al </li></ul><ul><li>procesador.*/ </li></ul><ul><li>26221 static inline void reschedule_idle( </li></ul><ul><li>26222 struct task_struct * p) </li></ul><ul><li>26223 { </li></ul><ul><li>26224 </li></ul><ul><li>/* Si es proceso en tiempo real o tiene más cuanto de tiempo por </li></ul><ul><li>consumir que el actual hay que replanificar */ </li></ul><ul><li>26225 if (p->policy != SCHED_OTHER || </li></ul><ul><li>26226 p->counter > current->counter + 3) { </li></ul><ul><li>26227 current->need_resched = 1; </li></ul><ul><li>26228 return; </li></ul><ul><li>26229 } </li></ul><ul><li>26269 } </li></ul>
  41. 41. Otras funciones <ul><li>/*Esta función despierta un proceso estableciendo el estado a </li></ul><ul><li>RUNNING. Si no está en lista de ejecución lo añade.*/ </li></ul><ul><li>26356 void wake_up_process(struct task_struct * p) </li></ul><ul><li>26357 { </li></ul><ul><li>26358 unsigned long flags; </li></ul><ul><li>/* Se pone el estado a TASK_RUNNING */ </li></ul><ul><li>26361 p->state = TASK_RUNNING; </li></ul><ul><li>/* Si no está en la cola lo añade */ </li></ul><ul><li>26362 if (!p->next_run) { </li></ul><ul><li>26363 add_to_runqueue(p); </li></ul><ul><li>26364 reschedule_idle(p); </li></ul><ul><li>26365 } </li></ul><ul><li>26367 } </li></ul>
  42. 42. Otras funciones <ul><li>/*Esta función actualiza el cuanto de tiempo restante de un proceso y </li></ul><ul><li>sus campos de contabilidad.*/ </li></ul><ul><li>27382 static void update_process_times(unsigned long ticks, unsigned long system) </li></ul><ul><li>27384 { </li></ul><ul><li>27387 struct task_struct * p = current; </li></ul><ul><li>27388 unsigned long user = ticks - system; </li></ul><ul><li>/* Se actualiza el cuanto de tiempo */ </li></ul><ul><li>p->counter -= ticks; </li></ul><ul><li>/* Si el contador ha expirado se pone a 0 y se manda a replanificar */ </li></ul><ul><li>27391 if (p->counter < 0) { </li></ul><ul><li>27392 p->counter = 0; </li></ul><ul><li>27393 p->need_resched = 1; </li></ul><ul><li>27400 } </li></ul><ul><li>/* Se actualizan los campos de contabilidad del proceso */ </li></ul><ul><li>27401 update_one_process(p, ticks, user, system, 0); </li></ul><ul><li>27403 } </li></ul>

×