Sunteți pe pagina 1din 80

2.

Procesos e hilos
Sistemas Operativos
Grado en Ingeniera Informtica
Grupo A
Jos Antonio Gmez Hernndez, 2014

SO - Jos Antonio Gmez, 2014

Contenidos
Repaso:
Conceptos de proceso e hilo
Diagrama de estados de procesos/hilos: estados y transiciones

Implementacin de procesos/hilos en Linux:


Diagrama de estados y transiciones
Operaciones sobre procesos

Planificacin de procesos:

Tipos de planificacin y planificadores


Algoritmos: FCFS, Prioridades, Roun-robin, CFS (Linux)
Planificacin en multiprocesadores
Planificacin en SOS de tiempo-real

SO - Jos Antonio Gmez, 2014

Repaso conceptos
Algunos conceptos que necesitamos tener claros:

Qu es un proceso y un hilo
Imagen de un proceso
Bloque de control de proceso y bloque control de hilo
Estados de procesos
Transiciones entre estados y ejemplo de eventos que las
provocan
Cambio de contexto (o proceso)

SO - Jos Antonio Gmez, 2014

Procesos en Linux
Un proceso representado por el descriptor de proceso o
estructura task_struct (definida en linux/sched.h).

SO - Jos Antonio Gmez, 2014

Estructura thread_info
Deriva el descriptor de un proceso a partir del puntero a pila.
Campos relevantes:
Indicadores TIF_SIGPENDING
y TIF_NEED_RESCHED
cpu: nmero CPU en la que
se ejecuta.
preempt_count: contador de
apropiacin
Macros:
current_thead_info :
direccin de thread_info del
proceso actual.
current: direccin del
descriptor del proceso del
proceso actual.
SO - Jos Antonio Gmez, 2014

Identificacin de
procesos/hilos
El sistema identifica a un proceso por su PID.
Su tipo opaco es pid_t, y suele ser un int.
Por compatibilidad hacia atrs el valor por defecto mximo
es 32768 (short int).
Podemos aumentarlo a travs de /proc/sys/kernel/pid_max,
necesario en grandes servidores.
Un hilo se identifica con un TID.
El estndar POSIX espera que todas las hebras del grupo
tengan el mismo PID.
Linux asigna a un grupo de hilos el PID del lider del grupo
(primer hilo), este se almacena en el tgid.
La funcin getpid() devuelve el valor de tgid. En breve,
veremos como obtener el tid de un hilo.
SO - Jos Antonio Gmez, 2014

Estados de procesos
El campo state almacena el estado de un proceso Linux:
TASK_RUNNING: El proceso es ejecutable o esta en ejecucin.
TASK_INTERRUPTIBLE: el proceso esta bloqueado (dormido) de
forma que puede ser interrumpido por una seal.
TASK_UNINTERRUPTIBLE: proceso bloqueado no despertable por
una seal.
TASK_TRACED: proceso que esta siendo traceado por otro.
TASK_STOPPED: la ejecucin del proceso se ha detenido por
algunas de las seales de control de trabajos.

El campo exit_state almacena los estados de los procesos


que ha finalizado:
EXIT_DEAD: el proceso va a ser eliminado pues su padre a
realizado un wait():
EXIT_ZOMBIE: El padre an no ha realizado wait().
SO - Jos Antonio Gmez, 2014

Diagrama de estados

SO - Jos Antonio Gmez, 2014

Transiciones y colas
sleep_on() - duerme a un proceso de forma ininterrumpible y
lo coloca en la cola de espera (wait queues) del evento
indicado como argumento.
interruptible_sleep_on() - duerme de forma interrumpible.
wake_up() - despierta a un proceso dormido ininterrup.
wake_up_interruptible() - idem interrumpible.
Existe una lista de procesos doblemente enlazada con todos
los procesos del sistema y a la cabeza esta el swapper
(PID=0, task_struct_init_task).
Los estados TASK_STOPPED, EXIT_ZOMBIE, EXIT_DEAD no
estn agrupados en colas.
Los procesos TASK_RUNNING estn en diferentes colas de
procesos ejecutables (ver planificacin).
SO - Jos Antonio Gmez, 2014

Cambio de estado actual


Podemos cambiar el estado de un proceso con las funciones
internas del kernel:
set_task_state(task, state); /*pone la tarea al estado
indicado*/
task->state = state;
set_current_state(state)=set_task_state(current, state)

SO - Jos Antonio Gmez, 2014

10

Jerarqua de procesos
Todos los sistemas Unix/Linux mantienen a los procesos en una
jerarqua:
El proceso init (PID=1) es el padre de todos los procesos.
Todo proceso tiene exactamente un padre
Todo proceso tiene 0 o ms hijos.

Denominamos hermanastros (siblings) a los procesos hijos del


mismo padre.
La relacin entre procesos se almacena en el descriptor de
proceso:
parent: puntero al padre
children: lista de hijos.

Podemos localizar el padre: my_parent=current->parent


Recorrer la lista de hijos: list_for_children(list, &current>children)

SO - Jos Antonio Gmez, 2014

11

Creacin de procesos
fork() crea un proceso idntico al llamador
exec() ejecuta un programa dentro de un proceso
En Linux, fork() se construye basndose en la llamada al sistema
clone(), que sirve para crear tanto procesos como hilos.
El trabajo de clone lo realiza do_fork() - definida en kernel/fork.c:
1.dup_task_struct() copia el descriptor del proceso actual.
2. Ajustamos varios campos del nuevo task_struct para diferenciarlo de su
padre.
3. Lo ponemos a TASK_UNINTERRUPTIBLE para que no se ejecute an.
4.copy_process() copia las sub-estructuras segn los indicadores
5. Con alloc_pid() le asignamos un nuevo PID.
6. Duplica las sub-estructuras indicadas por los argumentos de clone().
7. Retorna al llamador un puntero al nuevo hijo.

fork() se implementa como clone(SIGCHLD,0).


vfork() como clone(CLONE_VFORK|CLONE_VM|SIGCHLS, 0)
SO - Jos Antonio Gmez, 2014

12

Esquema

SO - Jos Antonio Gmez, 2014

13

clone()

Indicador

Significado

CLONE_FILES
CLONE_FS
CLONE_VM
CLONE_SIGHAND
CLONE_THREAD
CLONE_VFORK

Padre e hijo comparten los archivos abiertos


Padre e hijo comparten informacin del sistema de archivos
Padre e hijo comparten el espacio de direcciones
Comparten manejadores de seales y seales bloqueadas
Padre e hijo en el mismo grupo de hilos
Se invoc vfork; el padre duerme hasta el hijo lo despierta
SO - Jos Antonio Gmez, 2014

14

Creacion de hilos
Creamos un hilo (hebra) con la llamada:
clone(CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND,0)
Es decir, creamos un proceso que comparte con su llamador
el espacio de direcciones (VM) y los recursos (FS, FILES y
SIGHAND).
Hilos kernel hebras que no tienen un espacio de
direcciones de usuario (task_struct->mm=NULL) y realizan
labores de sistema. Sustituyen a los antiguos demonios.
Estas se crean a travs de otras hebras kernel con
*kthread_create() en el estado bloqueado, y, por tanto, hay
que despertarlas con wake_up_process().

SO - Jos Antonio Gmez, 2014

15

Ejemplo de clone() (i)


#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <linux/unistd.h>
#include <sys/syscall.h>
#include <errno.h>
#include <sched.h>
int var=5;
int thread(void *p) {
int tid;
var++;
tid = syscall(SYS_gettid);
printf("Hijo: %d %d, varh: %d\n", getpid(), tid, var);
}
SO - Jos Antonio Gmez, 2014

16

Ejemplo (y ii)
main() {
unsigned char stack[4096];
int i, tid;
setbuf(stdout, NULL);
i = clone(thread, (void **) stack+2048, CLONE_VM|
CLONE_FILES |CLONE_FS|CLONE_THREAD|CLONE_SIGHAND, NULL);
if (i == -1)
perror("clone");
else
printf("clone retorna: %d\n", i);
tid = syscall(SYS_gettid);
printf("padre: %d %d, varp: %d\n", getpid(), tid, var);
}
SO - Jos Antonio Gmez, 2014

17

Ejecucin
Si compilamos y ejecutamos el ejemplo tal como esta:
./clon
Hijo: 6633 6634, varh: 6
padre: 6633 6633, varp: 6
Si solo dejamos: i = clone(thread, (void **) stack+2048,
CLONE_FILES, NULL);
./clon
padre: 6463 6463, varp: 5
Hijo: 6464 6464, varh: 6
Qu esta pasando?

SO - Jos Antonio Gmez, 2014

18

Actividad en grupo
En el ejemplo anterior, hemos utilizado la funcin clone()
con los argumentos siguientes:
CLONE_VM|CLONE_FILES|CLONE_FS|CLONE_THREAD|CLONE_SIGHAND
Hacer un dibujo que represente las task_struct de ambos
procesos

SO - Jos Antonio Gmez, 2014

19

Terminacin de procesos
Se produce cuando un proceso invoca a voluntariamente a _exit() o
involuntariamente cuando recibe una seal.
La funcin que finaliza un proceso es do_exit() -kernel/exit.c:
Activa PF_EXITING
Decrementa los contadores de uso de mm_struct, fs_struct, files_struct. Si
estos contadores alcanzan el valor 0, destruye los recursos.
Ajusta el exit_code del descriptor, que ser devuelto al padre, con el valor pasado
a exit().
Envia al padre la seal de finalizacin; si tiene algn hijo le busca un padre en el
grupo o el init, y pone el estado a TASK_ZOMBIE.
Invoca a schedule() para ejecutar otro proceso.

Solo queda del proceso la pila kernel, la estructura thread_info y la


task_struct, de cara a que el padre pueda recuperar el cdigo de
finalizacin. Cuando se libera el resto?

SO - Jos Antonio Gmez, 2014

20

La llamada wait()
Wait(): llamada que bloquea a un proceso padre hasta que
uno de sus hijo finaliza; cuando esto ocurre, le devuelve el
PID del hijo finalizado. Adems, devuelve un puntero a la
funcin a tras retornar tiene el cdigo de finalizacin del
hijo.
Esta funcin invoca a release_task() que:
Elimina el descriptor de la lista de tareas.
Si es la ltima tarea de su grupo, y el lder esta zombi, notifica
al padre del lder zombi.
Libera la memoria de la pila kernel,thread_info y task_struct.

SO - Jos Antonio Gmez, 2014

21

Procesos hijos sin padre


Qu ocurre sin un proceso finaliza antes que sus hijo?
Como no deseamos que existan procesos zombis, debemos
asignar un nuevo padre al proceso(s): si es posible al grupo
de hilo al que pertenece, sino al proceso init.
De esto se encarga la funcin find_new_reaper() dentro de
do_exit().

SO - Jos Antonio Gmez, 2014

22

Planificacin
Tipos de planificadores:
Estudio individual: Apartado 9.1 del Stallings Tipos de
planificacin del procesador.

Tipos de planificacin
Criterios y algoritmos de planificacin
Planificacin en Linux:
CFS (Completely Fair Scheduler).
Planificacin en tiempo-real
Planificacin en multiprocesadores

SO - Jos Antonio Gmez, 2014

23

Tipos de planificadores
Planificador a largo
plazo procesos batch
Planificador a medio
plazo gestin de
memoria
Planificador a corto
plazo o simplemente
scheduler o
planificador

SO - Jos Antonio Gmez, 2014

24

Tipos de planificacin
Las polticas de planificacin se puede dividir en dos tipos:
Planificacin apropiativa (preemptive) Al proceso actual se le
puede retirar el control de la CPU bien por otro proceso, bien
por algn componente del sistema operativo.
Planificacin no apropiativa (non preemptive) Al proceso
actual NO se le puede retirar el control por ningn proceso o
componente del SO; slo el proceso actual puede ceder el
control de la CPU.

SO - Jos Antonio Gmez, 2014

25

Linux y apropiatividad
Los kernels actuales de Linux permiten ajustar el grano de
apropiatividad del sistema dependiendo del uso que
vayamos a hacer del mismo.
Define puntos de apropiacin: seccin del cdigo en la que
es posible apropiar al proceso actual para ceder la CPU a
otra funcin del sistema o proceso.
Las RSIs no invocan al planificador directamente, sino que
lo hacen de forma retardada activando la bandera
TIF_NEED_RESCHED=1, marcando que cuando sea posible se
debe planificar.
Cuando la ejecucin kernel alcanza un punto de apropiacin
(las EDs del kernel estan seguras), se mira el estado de la
bandera, y si esta a 1, se invoca al planificador.
SO - Jos Antonio Gmez, 2014

26

Apropiatividad en Linux
Debemos modificar las RSIs para invocar de forma
asncrona, y diferida, el planificador.
Por tanto tenemos dos formas de invocacin del
planificador: sincrona y asncrona.

TIF_NEED_RESCHED=1;

SO - Jos Antonio Gmez, 2014

27

Trabajo en Grupo 2.2.


Suponemos que estamos diseando el planificador a corto
plazo de un SO, y no enfrentamos a la situacin donde
debemos programar que debe hacer el planificador cuando
la cola de procesos preparados est vaca, por ejemplo,
porque no hay procesos o los que hay estn bloqueados.
Pasos:
Modificar el planificador visto en Tema 0, para que controle la
posibilidad de que la cola este vaca.
La solucin dada puede ser funcionalmente correcta pero puede
tener algn problema de eficiencia.
Podemos hacerla ms eficiente?

SO - Jos Antonio Gmez, 2014

28

Solucin a TG 2.2
1 solucin:
Planificador() {
while (true) {
if (cola_preparados==vacia)
halt;
else {
Selecciona (Pj);
Cambio_contexto(Pi,Pj);
}
}

2 solucin: optimizacin
while (true){
Selecciona (Pj);
Cambio_contexto(Pi,Pj);
}
Creamos un proceso nulo
u ocioso:
siempre preparado
menor prioridad del
sistema

SO - Jos Antonio Gmez, 2014

29

TG 2.2: solucin
La funcin de planificacin debera comprobar antes de
seleccionar a un proceso que la cola de preparados no esta
vaca. Si esta vaca, necesitamos programar la CPU para hacer
una actividad no til, por ejemplo, un bucle ocioso o detener la
CPU con halt.
Esta solucin sera correcta pero obliga a ejecutar cdigo extra
(comprobar n elementos de la cola de preparados) cada vez
que invoquemos al planificador. Cmo este cdigo se ejecuta
cientos de miles de veces, sera mucho tiempo desperdiciado.
Podemos optimizar la solucin anterior, introduciendo un
proceso que siempre este preparado, el proceso nulo, con lo
cual podemos quitar esa comprobacin. Adems, como el
proceso no debe competir con el resto por el uso de CPU, debe
tener la menor prioridad posible.
SO - Jos Antonio Gmez, 2014

30

Trabajo en grupo 2.3


Si utilizamos una planificacin NO apropiativa puede el
procesador manejar una interrupcin mientras esta
ejecutando al proceso actual?

SO - Jos Antonio Gmez, 2014

31

TG 2.3: solucin
En principio una poltica no apropiativa no permitira que se
atendiesen las interrupciones. Ahora bien, esto provocara
bastante irresponsividad del sistema.
Podemos atender las interrupciones sin violar la poltica de
planificacin de procesos siempre y cuando esto no
provoque un cambio de procesos. Es decir, antes de que se
produzca la interrupcin y despus de tratarla, el proceso
en ejecucin es el mismo Las RSIs no invocan al
Planificador.

SO - Jos Antonio Gmez, 2014

32

Planificacin en tiempo-real
El planificador tiene ordenar la ejecucin de las tareas a
preparadas de forma que cada una pueda cumplir el plazo
(deadline) asociado.
Esto nos obliga entre otras cosas a:
Desarrollar kernel apropiativos: objetivo, reducir la latencia de
despacho para poder planificar en el tiempo correcto la tarea
que debe responder a un evento.
Desarrollar algoritmos de planificacin que tengan en cuenta
los plazos de la tareas, cosa que no ocurre en los sistemas
operativos de propsito general.
Adaptaciones: algoritmo EDF (Early Deadline First).

SO - Jos Antonio Gmez, 2014

33

Latencia de despacho

Protocolos para evitar la inversin de prioridad: herencia de


prioridad y protocolo tope.
SO - Jos Antonio Gmez, 2014

34

Algoritmos y Criterios
En el Apartado 9.2 Algoritmos de planificacin del
Stallings podemos ver los algoritmos de planificacin ms
comunes.
Nosotros slo veremos los algoritmos generales:

FIFO
Prioridades
Round-Robin
Realimentacin (Feedback)

La Tabla 9.2 del libro de Stallings algunos de los criterios


(mtricas) de planificacin.
Estudiarlos como trabajo individual para poder abordar el
trabajo en grupo entregable del tema.

SO - Jos Antonio Gmez, 2014

35

Planificador de Linux
Implementado en la funcin schedule() en kernel/sched.c.
El planificador genrico tiene dos componentes:
Componente activado por un proceso al bloquearse o ceder la
CPU.
Componente peridico que se activa cada cierto tiempo.

El planificador interacciona adems con las clases de


planificacin:
De tiempo-real: SCHED_FIFO y SCHED_RR
De tiempo compartido: SCHED_NORMAL,SCHED_BATCH, SCHED_IDLE

SCHED_FIFO, SCHED_RR y SCHED_OTHERS definidas por


POSIX1.b.
El planificador de Linux soporta: mquina NUMA y UMA,
multicores e hiperthrearing.
SO - Jos Antonio Gmez, 2014

36

Componentes del planificador


Planificador genrico
Planificador
principal

Tiempo-real
FIFO

Planificador
peridico

Tiempo-real
roun-robin

Cambio
contexto

CFS

CPU

Clases de
planificacin

Tareas
SO - Jos Antonio Gmez, 2014

37

Elementos en task_struct
Algunos elementos del task_struct relacionados con
planificacin:

prio: prioridad usada por el planificador


rt_priority: prioridad de tiempo-real.
sched_class: clase de planificacin del proceso.
sched_entity: el mecanismo grupos de control establece que se
planifiquen entidades (procesos o grupos de procesos).

SO - Jos Antonio Gmez, 2014

38

task_struct (cont.)
policy: almacena la poltica de planificacin aplicada al
proceso:
SCHED_NORMAL: manejados por CFS al igual que:
SCHED_BATCH: procesos batch -no interactivos- acotados por
computo, son desfavorecidos por las decisiones de planificacin.
Nunca apropian a otro proceso gestionado por CFS y por interfieren
con trabajos interactivos. Es aconsejable en situaciones en las que
no se desea decrementar la prioridad esttica con nice, pero la
tarea no debera influenciar la interactividad del sistema.
SCHED_IDLE: tareas de poca importancia con peso relativo mnimo.
No es responsable de planificar la tarea ociosa.

SCHED_RR y SCHED_FIFO: implementan procesos de tiempo-real


soft. Gestionados por la clase de tiempo-real.

SO - Jos Antonio Gmez, 2014

39

Clases de planificacin
Suministran la conexin entre el planificador genrico y el planificador individual.
struct sched_class {
const struct sched_class *next;
void (*enqueue_task(); /* aade proceso a la cola de ejecucin rq, y nr_running++*/
void (*dequeue_task(); /* lo elimina de rq, y nr_running-- */
void (*yield_task) (); /* cede el control de la CPU*/
struct task_struct * (*pick_next_task) ();/*selecciona siguiente tarea a ejecutar*/
void (*put_prev_task)(); /* retira a la tarea del procesador */
void (*set_curr_task)(); /* se invoca al cambiar tarea de clase*/
void (*task_tick)(); /* invocada por el planificador periodico en cada invocacin */
void (*task_new)(); /* notifica al planificador de la creacin de una tarea */
. . .
};
Hay una instancia de la estructura por clase de planificacin.
Forman una jerarqua plana: procesos tiempo-real > procesos CFS > procesos idle.
La jerarqua se establece en tiempo de compilacin (no hay mecanismo para aadir una nueva clase
dinmicamente).

SO - Jos Antonio Gmez, 2014

40

Cola de ejecucin
Cada procesador tiene su cola de ejecucin (rq) y cada proceso
esta en una nica cola.
struct rq {
unsigned long nr_running; /* n procesos ejecutables */
#define CPU_LOAD_IDX_MAX 5;
unsigned long cpu_load[CPU_LOAD_IDX:MAX]; /*historico de la carga*/
struct load_weight load; /*carga de la cola */
struct cfs_rq cfs; /* cola embebida para cfs*/
struct rt_rq rt; /*cola embebida para rt*/
struct task_struct *curr, *idle; /*procesos actual y ocioso*/
u64 clock; /* reloj por cola; actualizado al invocar al
planificador periodico*/
. . .
}

SO - Jos Antonio Gmez, 2014

41

Entidades de planificacin
La estructura que describe una entidad es:
struct sched_entity {
struct load_weight load;
struct rb_node run_node;
unsigned int on_rq;
u64
u64
u64
u64
. .

/*para equilibrio de carga*/


/*nodo de arbol rojo-negro*/
/* indica si la entidad esta
planificada en una cola*/
exec_start;
/* tiempo inicio ejecucin */
sum_exec_start;
/t consumido de CPU*/
vrtime;
/*tiempo virtual */
prev_sum_exec_runtime; /* valor salvado de sum_exec_start
al quitarle control CPU*/
.

};
SO - Jos Antonio Gmez, 2014

42

Prioridades
El kernel utiliza un rango de prioridades siguiente

+ prioridad

-20

Tiempo-real
0

valor nice +19


normal

99 100

139

Valores de prioridad mostrados por el sistema Linux mantiene hasta


8 valores de prioridad por compatibilidad:

prioirity
intpri
opri
pri_foo
pri_bar
pri_baz
pri
pri_api

p->prio
60 + p->prio
top: muestra el valor de ps -o priority
60 + p->prio
ps con:
p->prio - 20
-l muestra el valor intprio
p->prio + 1
-l -c muestra -o pri
p->prio + 100
39 - p->priority
-1 - p->priority
SO - Jos Antonio Gmez, 2014

43

Poltica de planificacin
El planificador siempre selecciona para ejecucin al
proceso con mayor prioridad.
Si hay dos procesos con la misma prioridad, ejecutar al
que lleva ms tiempo esperando.
Si el proceso pertenece a la clase FIFO, lo ejecutar hasta
el final o hasta que se bloquee.

SO - Jos Antonio Gmez, 2014

44

Calculo de pesos de carga


La importancia de una tarea viene dada por su prioridad y
por su peso de carga (load weight).
Idea: un proceso que cambia disminuye su prioridad en un
nivel nice obtiene el 10% ms de CPU, mientras que
aumentar un nivel resta un 10% de CPU.
Para ello, el kernel convierte prioridades de peso de carga:
static
/* -20
/* -15
/* -10
/* -5
/*
0
/*
5
/* 10
/* 15
};

const int prio_to_weight[40] = {


*/
88761,
71755,
56483,
*/
29154,
23254,
18705,
*/
9548,
7620,
6100,
*/
3121,
2501,
1991,
*/
1024,
820,
655,
*/
335,
272,
215,
*/
110,
87,
70,
*/
36,
29,
23,
SO - Jos Antonio Gmez, 2014

46273,
14949,
4904,
1586,
526,
172,
56,
18,

36291,
11916,
3906,
1277,
423,
137,
45,
15,

45

Pesos de carga
La matriz contiene un valor para cada nivel nice en el rango
[0,39]. El multiplicador entre entradas es 1.25.
Ejemplos uso:
Dos procesos con nice 0: cada uno obtiene el 50% de CPU:
1024/(1024+1024).
Si un proceso sube un nivel nice (incrementa prioridad en 1)
decrementa su peso (1024/1.25 820). Ahora 1024/(1024+820)=
0.55 y 820/(1024+820)=0.45. Un proceso obtiene el 55% de CPU
y el otro un 45% (una diferencia del 10%).

La funcin que realiza estos clculos es set_load_weight().

SO - Jos Antonio Gmez, 2014

46

El planificador peridico
Implementado por scheduler_tick() se invoca con una
frecuencia de HZ, en update_process_times() para cargar el
tick actual al proceso actual (En kernel/timer.c)
Tiene dos funciones principales:
Manejar las estadsticas kernel relativas a planificacin.
Activar el planificador peridico de la clase de planificacin
responsable del proceso actual, delegando la labor en el
planificador de clase:
curr->sched_class->task_tick(rq, curr);

Si debemos replanificar la tarea actual, el mtodo de la


clase bsicamente activa el bit TIF_NEED_RESCHED.

SO - Jos Antonio Gmez, 2014

47

El planificador principal
La funcin schedule() se invoca directamente en diversos
puntos del kernel para cambiar de proceso.
Adems, cuando retornamos de una llamada al sistema,
comprobamos si hay que replanificar mediante
TIF_NEED_RESCHED, y si es necesario se invoca a schedule().
La funcin la podemos ver en
http://lxr.linux.no/#linux+v3.1/kernel/sched.c#L4260.

SO - Jos Antonio Gmez, 2014

48

Planificador principal (ii)


Las acciones principales son:
1. Seleccionar la cola y el proceso actual:
rq=cpu_rq(cpu);
prev=rq->cur;
2. Desactivar la tarea actual de la cola.
desactivate_task(rq, prev, 1);
3. Seleccionar el siguiente proceso a ejecutar.
next=pick_next_task(rq, next);
4. Invocar al cambio de contexto:
if (likely(prev!=next)
context_switch(rq, prev, next);

5. Comprobar si hay que replanificar:


if (need_resched())
goto need_resched;
SO - Jos Antonio Gmez, 2014

49

Cambio de contexto
El cambio de contexto descansa en las funciones:
switch_mm() que cambia el contexto de memoria de usuario
descrito por task_struct->mm
switch_to(prev,next,prev) que cambia los contenidos de los
registros del procesador y la pila kernel. Su formato equivale a
prev=switch(prev, next).

Si la tarea entrante o saliente es una hebra kernel utiliza un


mecanismo denominado TLB perezoso, en el que se indica
al procesador que realmente no hay que conmutar de
memoria.

SO - Jos Antonio Gmez, 2014

50

Clase CFS: definicin


Definida en kernel/sched_fair.c:
static const struct sched_class fair_sched_class = {
.next=&idle_sched_class,
.enqueue_task= enqueue_task_fair,
.dequeue_task= dequeue_task_fair,
.yield_task= yield_task_fair,
.check_preempt_curr= check_preempt_wakeup,
.pick_next_task= pick_next_task_fair,
.put_prev_task= put_prev_task_fair,
. . .
.task_tick= task_tick_fair,
. . .
}
SO - Jos Antonio Gmez, 2014

51

Clase CFS
CFS (Complety Fair Scheduler) intenta modelar un procesador
multitarea perfecto.
No asigna rodajas de tiempo a los procesos, asigna una
proporcin del procesador que depende de la carga del sistema
cada proceso se ejecuta durante un tiempo proporcional a su
peso dividido por la suma total de pesos.
TimeslicePi = (PesoPi / PesosPj ) P

Donde

P =

sched_latency si n>nr_latency

Min_granularidad x n en otro caso


Como el tiempo asignado tiende a cero conforme crece el
nmero de procesos, define una granularidad mnima= suelo de
tiempo asignado).
En la implementacin actual: sched_latency=8, nr_latency=8 y
min_granularity= 1 us.
SO - Jos Antonio Gmez, 2014

52

Tiempo asignado a proceso


Para calculo tiempo asignado se usa un periodo:
5 o menos procesos: 20ms
Sistema cargado: 5ms ms por proceso.

Tiempo asignado= (longitud periodo*peso)/peso rq


Ejemplo:
Proceso

P1

P2

P3

Nice

+5

-5

Peso

335

1024

3121

1.5 ms

4.5 ms

14 ms

Tiempo
asignado

SO - Jos Antonio Gmez, 2014

53

CFS: seleccin proceso


Tiempo virtual de ejecucin (vruntime)=tiempo de ejecucin
real normalizado por el nmero de procesos en ejecucin. Este
tiempo es gestionado por update_curr() definida en
kernel/sched_fair.c.
Vruntime= (PesoNice0/Perso cola)x tiempo_real
=tiempo_ejecucion_actual* 1024/peso rq
CFS intenta equilibrar los tiempos virtuales de ejecucin de los
procesos con la regla: se elige para ejecucin el proceso con
vruntime ms pequeo.
Cola de ejecucin de CFS rbol rojo-negro (rbtree): rbol de
bsqueda binario auto-equilibrado donde la clave de bsqueda
es vruntime. Insercin/borrado con O(log n).
El proceso con vruntime menor es la hoja ms a la izquierda en
el rbol.
SO - Jos Antonio Gmez, 2014

54

Ejemplo extrado de Ktown Coder, Process Scheduling


In Linux en www.countrycoders.com/comp314.php

SO - Jos Antonio Gmez, 2014

55

Parmetros planificacin
Lista de las variables relacionadas con planificacin:
% sysctl -A | grep "sched" | grep -v "domain"

Valor actual de las variables ajustables: /proc/sched_debug


Estadsticas cola actual: /proc/schedstat
Informacin planificacin proceso PID: /proc/<PID>/sched

SO - Jos Antonio Gmez, 2014

56

Clase de tiempo real


Si existe un proceso de
tiempo-real ejecutable en
el sistema este se
ejecutar antes que el
resto, salvo que haya otro
de prioridad mayor.
La cola de ejecucin es
simple:

SO - Jos Antonio Gmez, 2014

57

Planificacin SMP
Aspectos considerados:
Comparticin de la carga de CPU imparcial
Afinidad de una tarea por un procesador
Migracin de tareas sin sobrecarga

SO - Jos Antonio Gmez, 2014

58

Dominios de planificacin
La colas de ejecucin se organizan en
dominios de planificacin
Un dominio de planificacin agrupa CPUs
que comparten propiesades y algoritmos,
y que pueden equilibrase entre ellas.
Cada dominio contiene un o varios grupos
de CPUs que pueden tratarse como una
unidad.
Podemos configurar numerosos
parmetros en
/proc/sys/kernel/cpuX/domainY.

SO - Jos Antonio Gmez, 2014

59

Dominio de planificacin
struct sched_domain {
/* These fields must be setup */
struct sched_domain *parent;
struct sched_domain *child;
struct sched_group *groups;
unsigned long min_interval;
unsigned long max_interval;
unsigned int busy_factor;
unsigned int imbalance_pct;
unsigned int cache_nice_tries;
unsigned int busy_idx;
unsigned int idle_idx;
unsigned int newidle_idx;
unsigned int wake_idx;
unsigned int forkexec_idx;
unsigned int smt_gain;
int flags;
int level;

/*
/*
/*
/*
/*
/*
/*
/*

top domain must be null terminated */


bottom domain must be null terminated */
the balancing groups of the domain */
Minimum balance interval ms */
Maximum balance interval ms */
less balancing by factor if busy */
No balance until over watermark */
Leave cache hot tasks for # tries */

/* See SD_* */

/* Runtime fields. */
unsigned long last_balance;
/* init to jiffies. units in jiffies */
unsigned int balance_interval; /* initialise to 1. units in ms. */
unsigned int nr_balance_failed; /* initialise to 0 */
. . .
}

SO - Jos Antonio Gmez, 2014

60

Grupo de planificacin
struct sched_group {
struct sched_group *next;
atomic_t ref;

/* Must be a circular list */

unsigned int group_weight;


struct sched_group_power *sgp;
/*
* The CPUs this group covers.
*
* NOTE: this field is variable length. (Allocated dynamically
* by attaching extra space to the end of the structure,
* depending on how many CPUs the kernel has booted up with)
*/
unsigned long cpumask[0];
};

SO - Jos Antonio Gmez, 2014

61

Gestin de potencia
Un aspecto importante a considerar en los diseo
actuales es la gestin de potencia, encaminada a
mantener la potencia de cmputo reduciendo:
Los costes de consumo de energa
Los costes de refrigeracin
Esta gestin se puede realizar a varios niveles:
Nivel de CPU: P-states, C-states y T-states.
Nivel de SO: CPUfreq (paquetes cpufrequtils y
cpupower) y planificacin

SO - Jos Antonio Gmez, 2014

62

Especificacin ACPI
Advanced Configuration and Power
Interface: especificacin abierta para
la gestin de potencia y gestin
trmica controladas por el SO.
Desarrollada por Microsoft, Intel, HP,
Phoenix, y Toshiba.
Define cuatro estados Globales (Gestados):
G0: estado de funcionamiento:
estados-C y estados-P
G1: estado dormido S-estados
G2: Estado apagado soft
G3: Estado apagado mecanico

Techarp, PC Power Management Guide Rev. 2.0,


disponible en
http://www.techarp.com/showarticle.aspx?artno=420

SO - Jos Antonio Gmez, 2014

63

Estados de la CPU
S-estados : estados dormidos en
G1. Van de S1 a S5.
C-estados: estados de potencia
en G0. C0:activo, C1:halt, C2:stop,
C3, deep sleep,...
P-estados : relacionados con el
control de la frecuencia y el
voltaje del procesador. Se usan
con G0 y C0. P1-Pn, a mayor n
menos freq y volt.
T-estados : estados throttles
relativos a la gestin trmica.
Introducen ciclos ociosos.
ACPI spec v5.0, Dic. 2011
SO - Jos Antonio Gmez, 2014

64

Estructura CPUfreq
El subsistema CPUfreq es el responsable de ajustar
explcitamente la frecuencia del procesador.
Estructura modularizada que separa polticas (gobernadores)
de mecanismos (drivers especficos de CPUs).
Gobernadores
a nivel usuario
Gobernadores
en el kernel

Powersaved
Performance

Powersave

cpuspeed

Userspace

Conservative

Ondemand

Mdulo CPUfreq (interfaces /proc y /sys)


Drivers especficos
De CPU

acpi-cpufreq

speedstep-centrino

Powernow-k8

Driver ACPI del procesador

SO - Jos Antonio Gmez, 2014

65

Gobernadores
Performace mantiene la CPU a la mxima frecuencia
posible dentro un rango especificado por el usuario.
Powersave mantiene la CPU a la menor frecuencia posible
dentro del rango.
Userspace exporta la informacin disponible de frecuencia
a nivel de usuario (sysfs) permitiendo su control al mismo.
On-demand ajusta la frecuencia dependiendo del uso
actual de la CPU.
Conservative Como 'ondemand' pero ajuste ms gradual
(menos agresivo).
Podemos ver el gobernador por defecto en
/sys/devices/system/cpu/cpuX/scaling_governor

SO - Jos Antonio Gmez, 2014

66

Herramientas
Cpufrequtils podemos ver, modificar los ajustes del kernel
relativos al subsistema CPUfreq. Las rdenes cpufreq* son
utiles para modificar los estados-P, especialmente escalado
de frecuencia y gobernadores.
Cpupower ver todos los parmetros relativos a potencia de
todas las CPUs, incluidos los estados-turbo. Engloba a la
anterior.
PowerTOP ayuda a identificar las razones de un consumo
alto innecesario, por ejemplo, procesos que despiertan al
procesador del estado ocioso.
Se pueden crear perfiles en /etc/pm-profiler.

SO - Jos Antonio Gmez, 2014

67

Planificacin y energa
En CMP con recursos compartidos entre ncleos de un
paquete fsico, el rendimiento mximo se obtiene cuando el
planificador distribuye la carga equitativamente entre todos
lo paquetes.
En CMP sin recursos compartidos entre ncleos de un
mismo paquete fsico, se ahorrar energa sin afectar al
rendimiento si el planificador distribuye primero la carga
entre ncleos de un paquete, antes de buscar paquetes
vacos.

SO - Jos Antonio Gmez, 2014

68

Algoritmos de planificacin
El administrador puede elegir el algoritmo de planificacin
moficando las entradas sched_mc_power_saving y

sched_smt_power_saving de /sys/devices/system/cpu/
Rendimiento ptimo

Ahorro de energa

SO - Jos Antonio Gmez, 2014

69

Grupos de control
El planificador trata con entidades planificables,
que no tienen por que ser procesos.
Esto permite definir grupos de planificacin
Diferentes procesos se asignan a diferentes
grupos. El planificador reparte la CPU
imparcialmente entre grupos, y luego entre
proceso de un grupo. Esto reparte imparcialmente
la CPU entre usuarios.

SO - Jos Antonio Gmez, 2014

70

Grupos de control
Suministran un mecanismo para:

Asignar/limitar/priorizar recursos: CPU, memoria, y dispositivos.


Contabilidad: medir el uso de recursos.
Aislamiento: espacios de nombres separados por grupo.
Control: congelar grupos o hacer checkpoint/restart.

Los cgroups son jerrquicos: un grupo hereda los lmites del


grupo padre.

SO - Jos Antonio Gmez, 2014

71

Subsistemas de gc
Existen diferentes subsistemas (controladores de recursos):

cpu: utilizado por el planificador para suministrar el acceso de las tareas de un cgroup a la CPU.
cpuacct: genera automticamente informes de la CPU utilizada por las tareas de un cgroup.
cpuset: asigna CPUs individuales y memoria en sistemas multicore.
devices: permite/deniega el acceso de las tareas a un dispositivo.
freezer: detiene la ejecucin de todos los procesos de un grupo.
memory: limita el uso de memoria a tareas de un cgroup, y genera informes automticos del uso
de memoria de esas tarea.
blkio: establece los lmites de accesos de E/S desde/hacia dispositivos de bloques (discos, USB, ...)
net_cls: etiqueta paquetes de red con un identificador de clase (classid) que permite al
controlador de trfico (tc) identificar los paquetes originados en una tarea de un grupo.
ns:_subsitemas de espacios de nombres (namespaces), visto en Tema 1,

SO - Jos Antonio Gmez, 2014

72

Relaciones
Definiciones:

Tarea: proceso de usuario o kernel


Cgroup: una o ms tareas.
Subsistema: modulo que modifica el comportamiento de las
tareas de un cgroup.
Jerarqua: varios cgroups en un rbol.

Existen varias reglas que gobiernan la relacin entre


subsistemas, jerarquas, grupos de control y tareas
(procesos).
Hay cuatro reglas:

SO - Jos Antonio Gmez, 2014

73

Regla 1

SO - Jos Antonio Gmez, 2014

74

Regla 2

SO - Jos Antonio Gmez, 2014

75

Regla 3

SO - Jos Antonio Gmez, 2014

76

Regla 4

SO - Jos Antonio Gmez, 2014

77

Uso de los cgroups


Pueden utilizarse de diferentes modos:

Seudo-sistema de archivos cgroups (cgroupfs).


Herramientas de libcgroup: cgcreate, cgexec, cgclassify, ...
El demonio engine rules los gestiona segn la informacin de
los archivos de configuracin.
Indirectamente a travs de otros mecanismos como Linux
Containers (LXC), libvirt, systemd.

SO - Jos Antonio Gmez, 2014

78

Mtodo 1: Cgroups FS
Los subsistemas se habilitan como una opcin de montaje de
cgroupfs:
mount -t cgroup -o$subsistema

Habilitamos los archivos del subsistema en cada cgroup (directorio):


/dev/cgroup/migrupo/subsysA.optionB

Podemos verlos en /proc/cgroups.


En Ubuntu, podemos instalarlo con
$ sudo aptitude install cgroups-bin libcgroup1

Esto nos monta por defecto los siguientes fs:


$ ls -l /sys/fs/cgroup
cpu cpuacct devices memory

Podemos ver los grupos de control con cat /proc/cgroups

SO - Jos Antonio Gmez, 2014

79

CgroupsFS: ejemplo
Crear dos grupos para asignar tiempo de CPU:
Creamos el correspondiente subdirectorio en sys/fs/cgroup/cpu:

$ mkdir Navegadores; mkdir multimedia

Asignamos el porcentaje de cpu al grupo escribiendo en el archivo cpu.shares:

$ echo 2048 > /sys/fs/cgroup/cpu/multimedia/cpu.shares


$ echo 1024 > /sys/fs/cgroup/cpu/multimedia/cpu.shares

Movemos una tarea al cgrupo escribiendo su PID en el archivo tasks.

$
$
$
$

firefox&
echo $! > /sys/fs/cgroup/cpu/navegadores/tasks
mplayer micancion.mp3&
echo $! > /sys/fs/cgroup/cpu/multimedia/tasks

SO - Jos Antonio Gmez, 2014

80

S-ar putea să vă placă și