|
| 1 | +.. include:: ../disclaimer-sp.rst |
| 2 | + |
| 3 | +:Original: :ref:`Documentation/scheduler/sched-design-CFS.rst <sched_design_CFS>` |
| 4 | +:Translator: Sergio González Collado < [email protected]> |
| 5 | + |
| 6 | +.. _sp_sched_desing_CFS: |
| 7 | + |
| 8 | +==================== |
| 9 | +Gestor de tareas CFS |
| 10 | +==================== |
| 11 | + |
| 12 | +1. VISIÓN GENERAL |
| 13 | +================== |
| 14 | + |
| 15 | +CFS viene de las siglas en inglés de "Gestor de tareas totalmente justo" |
| 16 | +("Completely Fair Scheduler"), y es el nuevo gestor de tareas de escritorio |
| 17 | +implementado por Ingo Molnar e integrado en Linux 2.6.23. Es el sustituto de |
| 18 | +el previo gestor de tareas SCHED_OTHER. |
| 19 | + |
| 20 | +Nota: El planificador EEVDF fue incorporado más recientemente al kernel. |
| 21 | + |
| 22 | +El 80% del diseño de CFS puede ser resumido en una única frase: CFS |
| 23 | +básicamente modela una "CPU ideal, precisa y multi-tarea" sobre hardware |
| 24 | +real. |
| 25 | + |
| 26 | +"una CPU multitarea ideal" es una CPU (inexistente :-)) que tiene un 100% |
| 27 | +de potencia y que puede ejecutar cualquier tarea exactamente a la misma |
| 28 | +velocidad, en paralelo, y cada una a 1/n velocidad. Por ejemplo, si hay dos |
| 29 | +tareas ejecutándose, entonces cada una usa un 50% de la potencia --- es decir, |
| 30 | +como si se ejecutaran en paralelo. |
| 31 | + |
| 32 | +En hardware real, se puede ejecutar una única tarea a la vez, así que |
| 33 | +se ha usado el concepto de "tiempo de ejecución virtual". El tiempo |
| 34 | +de ejecución virtual de una tarea específica cuando la siguiente porción |
| 35 | +de ejecución podría empezar en la CPU ideal multi-tarea descrita anteriormente. |
| 36 | +En la práctica, el tiempo de ejecución virtual de una tarea es el |
| 37 | +tiempo de ejecución real normalizado con respecto al número total de |
| 38 | +tareas ejecutándose. |
| 39 | + |
| 40 | + |
| 41 | +2. UNOS CUANTOS DETALLES DE IMPLEMENTACIÓN |
| 42 | +=========================================== |
| 43 | + |
| 44 | +En CFS, el tiempo de ejecución virtual se expresa y se monitoriza por |
| 45 | +cada tarea, en su valor de p->se.vruntime (en unidades de nanosegundos). |
| 46 | +De este modo, es posible temporizar con precisión y medir el "tiempo |
| 47 | +de CPU esperado" que una tarea debería tener. |
| 48 | + |
| 49 | +Un pequeño detalle: en hardware "ideal", en cualquier momento todas las |
| 50 | +tareas pueden tener el mismo valor de p->se.vruntime --- i.e., tareas |
| 51 | +se podrían ejecutar simultáneamente y ninguna tarea podría escaparse del |
| 52 | +"balance" de la partición "ideal" del tiempo compartido de la CPU. |
| 53 | + |
| 54 | +La lógica de elección del tareas de CFS se basa en el valor de p->se.vruntime |
| 55 | +y por tanto es muy sencilla: siempre intenta ejecutar la tarea con el valor |
| 56 | +p->se.vruntime más pequeño (i.e., la tarea que se ha ejecutado menos hasta el |
| 57 | +momento). CFS siempre intenta dividir el espacio de tiempo entre tareas |
| 58 | +en ejecución tan próximo a la "ejecución multitarea ideal del hardware" como |
| 59 | +sea posible. |
| 60 | + |
| 61 | +El resto del diseño de CFS simplemente se escapa de este simple concepto, |
| 62 | +con unos cuantos añadidos como los niveles "nice" ("nice" significa "amable" |
| 63 | +en inglés), multi-tarea y varias variantes del algoritmo para identificar |
| 64 | +tareas "durmiendo". |
| 65 | + |
| 66 | + |
| 67 | +3. EL ÁRBOL ROJO-NEGRO |
| 68 | +======================= |
| 69 | + |
| 70 | +El diseño de CFS es bastante radical: no utiliza las antiguas estructuras |
| 71 | +de datos para las colas de ejecución (en inglés "runqueues"), pero usa una |
| 72 | +estructura de árbol rojo-negro (en inglés "red-black tree") ordenado cronológicamente |
| 73 | +para construir un línea de ejecución en el futuro, y por eso no tiene ningún |
| 74 | +artificio de "cambio de tareas" (algo que previamente era usado por el gestor |
| 75 | +anterior y RSDL/SD). |
| 76 | + |
| 77 | +CFS también mantiene el valor de rq->cfs.min_vruntime, el cual crece |
| 78 | +monotónicamente siguiendo el valor más pequeño de vruntime de entre todas |
| 79 | +las tareas en la cola de ejecución. La cantidad total de trabajo realizado |
| 80 | +por el sistema es monitorizado usado min_vruntime; este valor es usado |
| 81 | +para situar las nuevas tareas en la parte izquierda del árbol tanto |
| 82 | +como sea posible. |
| 83 | + |
| 84 | +El valor total de tareas ejecutándose en la cola de ejecución es |
| 85 | +contabilizado mediante el valor rq->cfs.load, el cual es la suma de los |
| 86 | +de esas tareas que están en la cola de ejecución. |
| 87 | + |
| 88 | +CFS mantiene un árbol rojo-negro cronológicamente ordenado, donde todas las |
| 89 | +tareas que pueden ser ejecutadas están ordenadas por su valor de |
| 90 | +p->se.vruntime. CFS selecciona la tarea más hacia la izquierda de este |
| 91 | +árbol y la mantiene. Según el sistema continúa, las tareas ejecutadas |
| 92 | +se ponen en este árbol más y más hacia la derecha --- lentamente pero |
| 93 | +de forma continuada dando una oportunidad a cada tarea de ser la que |
| 94 | +está "la más hacia la izquierda" y por tanto obtener la CPU una cantidad |
| 95 | +determinista de tiempo. |
| 96 | + |
| 97 | +Resumiendo, CFS funciona así: ejecuta una tarea un tiempo, y cuando la |
| 98 | +tarea se gestiona (o sucede un tic del gestor de tareas) se considera |
| 99 | +que el tiempo de uso de la CPU se ha completado, y se añade a |
| 100 | +p->se.vruntime. Una vez p->se.vruntime ha aumentado lo suficiente como |
| 101 | +para que otra tarea sea "la tarea más hacia la izquierda" del árbol |
| 102 | +rojo-negro ordenado cronológicamente esta mantienen (más una cierta pequeña |
| 103 | +cantidad de distancia relativa a la tarea más hacia la izquierda para |
| 104 | +que no se sobre-reserven tareas y perjudique a la cache), entonces la |
| 105 | +nueva tarea "que está a la izquierda del todo", es la que se elige |
| 106 | +para que se ejecute, y la tarea en ejecución es interrumpida. |
| 107 | + |
| 108 | +4. ALGUNAS CARACTERÍSTICAS DE CFS |
| 109 | +================================== |
| 110 | + |
| 111 | +CFS usa una granularidad de nanosegundos y no depende de ningún |
| 112 | +jiffie o detalles como HZ. De este modo, el gestor de tareas CFS no tiene |
| 113 | +noción de "ventanas de tiempo" de la forma en que tenía el gestor de |
| 114 | +tareas previo, y tampoco tiene heurísticos. Únicamente hay un parámetro |
| 115 | +central ajustable (se ha de cambiar en CONFIG_SCHED_DEBUG): |
| 116 | + |
| 117 | + /sys/kernel/debug/sched/base_slice_ns |
| 118 | + |
| 119 | +El cual puede ser usado para afinar desde el gestor de tareas del "escritorio" |
| 120 | +(i.e., bajas latencias) hacia cargas de "servidor" (i.e., bueno con |
| 121 | +procesamientos). Su valor por defecto es adecuado para tareas de escritorio. |
| 122 | +SCHED_BATCH también es gestionado por el gestor de tareas CFS. |
| 123 | + |
| 124 | +Debido a su diseño, el gestor de tareas CFS no es proclive a ninguno de los |
| 125 | +ataques que existen a día de hoy contra los heurísticos del gestor de tareas: |
| 126 | +fiftyp.c, thud.c, chew.c, ring-test.c, massive_intr.c todos trabajan |
| 127 | +correctamente y no tienen impacto en la interacción y se comportan de la forma |
| 128 | +esperada. |
| 129 | + |
| 130 | +El gestor de tareas CFS tiene una gestión mucho más firme de los niveles |
| 131 | +"nice" y SCHED_BATCH que los previos gestores de tareas: ambos tipos de |
| 132 | +tareas están aisladas de forma más eficiente. |
| 133 | + |
| 134 | +El balanceo de tareas SMP ha sido rehecho/mejorado: el avance por las |
| 135 | +colas de ejecución de tareas ha desaparecido del código de balanceo de |
| 136 | +carga, y ahora se usan iteradores en la gestión de módulos. El balanceo |
| 137 | +del código ha sido simplificado como resultado esto. |
| 138 | + |
| 139 | +5. Políticas de gestión de tareas |
| 140 | +================================== |
| 141 | + |
| 142 | +CFS implementa tres políticas de gestión de tareas: |
| 143 | + |
| 144 | + - SCHED_NORMAL (tradicionalmente llamada SCHED_OTHER): Gestión de |
| 145 | + tareas que se usan para tareas normales. |
| 146 | + |
| 147 | + - SCHED_BATCH: No interrumpe tareas tan a menudo como las tareas |
| 148 | + normales harían, por eso permite a las tareas ejecutarse durante |
| 149 | + ventanas de tiempo mayores y hace un uso más efectivo de las |
| 150 | + caches pero al coste de la interactividad. Esto es adecuado |
| 151 | + para trabajos de procesado de datos. |
| 152 | + |
| 153 | + - SCHED_IDLE: Esta política es más débil incluso que nice 19, pero |
| 154 | + no es un gestor "idle" para evitar caer en el problema de la |
| 155 | + inversión de prioridades que causaría un bloqueo de la máquina |
| 156 | + (deadlock). |
| 157 | + |
| 158 | +SCHED_FIFO/_RR se implementan en sched/rt.c y son específicos de |
| 159 | +POSIX. |
| 160 | + |
| 161 | +El comando chrt de util-linux-ng 2.13.1.1. puede asignar cualquiera de |
| 162 | +estas políticas excepto SCHED_IDLE. |
| 163 | + |
| 164 | + |
| 165 | +6. CLASES DE GESTIÓN |
| 166 | +===================== |
| 167 | + |
| 168 | +El nuevo gestor de tareas CFS ha sido diseñado de tal modo para incluir |
| 169 | +"clases de gestión", una jerarquía ampliable de módulos que pueden tener |
| 170 | +distintas políticas de gestión de tareas. Estos módulos encapsulan los |
| 171 | +detalles de las politicas de gestión y son manejadas por el núcleo del |
| 172 | +gestor de tareas sin que este tenga que presuponer mucho sobre estas clases. |
| 173 | + |
| 174 | +sched/fair.c implementa el gestor de tareas CFS descrito antes. |
| 175 | + |
| 176 | +sched/rt.c implementa la semántica de SCHED_FIFO y SCHED_RR, de una forma |
| 177 | +más sencilla que el gestor de tareas anterior. Usa 100 colas de ejecución |
| 178 | +(por todos los 100 niveles de prioridad RT, en vez de las 140 que necesitaba |
| 179 | +el gestor de tareas anterior) y no necesita las listas de expiración. |
| 180 | + |
| 181 | +Las clases de gestión de tareas son implementadas por medio de la estructura |
| 182 | +sched_class, la cual tiene llamadas a las funciones que deben de llamarse |
| 183 | +cuando quiera que ocurra un evento interesante. |
| 184 | + |
| 185 | +Esta es la lista parcial de llamadas: |
| 186 | + |
| 187 | + - enqueue_task(...) |
| 188 | + |
| 189 | + Llamada cuando una tarea entra en el estado de lista para ejecución. |
| 190 | + Pone la entidad a ser gestionada (la tarea) en el árbol rojo-negro |
| 191 | + e incrementa la variable nr_running. |
| 192 | + |
| 193 | + - dequeue_task(...) |
| 194 | + |
| 195 | + Cuando una tarea deja de ser ejecutable, esta función se llama para |
| 196 | + mantener a la entidad gestionada fuera del árbol rojo-negor. Esto |
| 197 | + decrementa la variable nr_running. |
| 198 | + |
| 199 | + - yield_task(...) |
| 200 | + |
| 201 | + Esta función es básicamente desencolar, seguido por encolar, a menos que |
| 202 | + sysctl compat_yield esté activado; en ese caso, sitúa la entidad a gestionar |
| 203 | + en la parte más hacia la derecha del árbol rojo-negro. |
| 204 | + |
| 205 | + - check_preempt_curr(...) |
| 206 | + |
| 207 | + Esta función comprueba si una tarea que ha entrado en el estado de |
| 208 | + poder ser ejecutada, podría reemplazar a la tarea que actualmente |
| 209 | + se esté ejecutando. |
| 210 | + |
| 211 | + - pick_next_task(...) |
| 212 | + |
| 213 | + Esta función elige la tarea más apropiada para ser ejecutada a continuación. |
| 214 | + |
| 215 | + - set_curr_task(...) |
| 216 | + |
| 217 | + Esta función se llama cuando una tarea cambia su clase de gestión o |
| 218 | + cambia su grupo de tareas. |
| 219 | + |
| 220 | + - task_tick(...) |
| 221 | + |
| 222 | + Esta función es llamada la mayoría de las veces desde la función de tiempo |
| 223 | + tick; esto puede llevar a un cambio de procesos. Esto dirige el reemplazo |
| 224 | + de las tareas. |
| 225 | + |
| 226 | + |
| 227 | +7. EXTENSIONES DE GRUPOS PARA CFS |
| 228 | +================================== |
| 229 | + |
| 230 | +Normalmente, el gestor de tareas gestiona tareas individuales e intenta |
| 231 | +proporcionar una cantidad justa de CPU a cada tarea. Algunas veces, puede |
| 232 | +ser deseable agrupar las tareas y proporcionarles una cantidad justa |
| 233 | +de tiempo de CPU a cada una de las tareas de ese grupo. Por ejemplo, |
| 234 | +podría ser deseable que primero se proporcione una cantidad justa de |
| 235 | +tiempo de CPU a cada usuario del sistema y después a cada tarea |
| 236 | +que pertenezca a un usuario. |
| 237 | + |
| 238 | +CONFIG_CGROUP_SCHED destaca en conseguir exactamente eso. Permite a las |
| 239 | +tareas ser agrupadas y divide el tiempo de CPU de forma just entre esos |
| 240 | +grupos. |
| 241 | + |
| 242 | +CONFIG_RT_GROUP_SCHED permite agrupar tareas de tiempo real (i.e., |
| 243 | +SCHED_FIFO y SCHED_RR). |
| 244 | + |
| 245 | +CONFIG_FAIR_GROUP_SCHED permite agrupar tareas de CFS (i.e., SCHED_NORMAL y |
| 246 | +SCHED_BATCH). |
| 247 | + |
| 248 | +Estas opciones necesitan CONFIG_CGROUPS para ser definidas, y permitir |
| 249 | +al administrador crear grupos arbitrarios de tareas, usando el pseudo |
| 250 | +sistema de archivos "cgroup". Vease la documentación para más información |
| 251 | +sobre este sistema de archivos: Documentation/admin-guide/cgroup-v1/cgroups.rst |
| 252 | + |
| 253 | +Cuando CONFIG_FAIR_GROUP_SCHED es definido, un archivo |
| 254 | +"cpu.shares" es creado por cada grupo creado usado en el pseudo |
| 255 | +sistema de archivos. Véanse por ejemplo los pasos a continuación |
| 256 | +para crear grupos de tareas y modificar cuanto comparten de la CPU |
| 257 | +usando el pseudo sistema de archivos "cgroup" :: |
| 258 | + |
| 259 | + # mount -t tmpfs cgroup_root /sys/fs/cgroup |
| 260 | + # mkdir /sys/fs/cgroup/cpu |
| 261 | + # mount -t cgroup -ocpu none /sys/fs/cgroup/cpu |
| 262 | + # cd /sys/fs/cgroup/cpu |
| 263 | + |
| 264 | + # mkdir multimedia # crear un grupo de tareas "multimedia" |
| 265 | + # mkdir browser # crear un grupo de tareas "browser" |
| 266 | + |
| 267 | + # #Configurar el grupo multimedia para tener el doble de tiempo de CPU |
| 268 | + # #que el grupo browser |
| 269 | + |
| 270 | + # echo 2048 > multimedia/cpu.shares |
| 271 | + # echo 1024 > browser/cpu.shares |
| 272 | + |
| 273 | + # firefox & # Lanzar firefox y moverlo al grupo "browser" |
| 274 | + # echo <firefox_pid> > browser/tasks |
| 275 | + |
| 276 | + # #Lanzar gmplayer (o su programa favorito de reproducción de películas) |
| 277 | + # echo <movie_player_pid> > multimedia/tasks |
0 commit comments