2009-12-12 6 views
7

Estoy ejecutando 2 hilos (supongamos que son subprocesos por el momento). Thread_1() hace una llamada API definida por el usuario que finalmente hace algo de trabajo en el kernel. Thread_2() está totalmente en espacio de usuario.¿Se puede anular un subproceso en medio de una llamada al kernel del sistema?

Mi pregunta es: ¿Puede Thread_2() comenzar a ejecutar al anular Thread_1() mientras la llamada API está en progreso, el control está en algún lugar dentro del kernel? De lo contrario, ¿por qué? Y si deseo que ocurra este escenario (por algún motivo), ¿qué debo hacer?

Respuesta

5

Si está preguntando si una llamada de kernel de bloqueo como fread() que requiere disco IO puede anularse, entonces sí.

Más específicamente, una llamada de bloqueo básicamente pondrá a Thread_1 en suspensión mientras espera lo que está esperando. Si Thread_1 está dormido, se programará la ejecución de Thread_2 (a menos que exista algo de mayor prioridad en espera para ejecutarse).

Editar: Si quieres una manera de ser "bastante seguro" de que Thread_1 está realizando una llamada de bloqueo, hacen Thread_2 prioridad más baja que Thread_1 (de modo que por lo general no se plazo, a menos Thread_1 se bloquea) y cuando se ejecuta, eleva su prioridad a un nivel más alto que Thread_1 hasta que se entregue la interrupción de hardware, momento en el que disminuye su prioridad y llama al sched_yield().

+0

En realidad, esto supone que su los hilos son manejados por kernel. Y algunos granos pueden variar. – Artelius

+0

¿Puede aclarar: la diferencia entre administrado por kernel y no por kernel? ¿Qué variaciones existen? – TCSGrad

+0

Los subprocesos gestionados por kernel son vistos por el kernel como un proceso único. El proceso interno (sin soporte de kernel) programa sus diversos hilos. Por lo general, si uno de estos subprocesos se bloquea, todo el proceso se ve bloqueado por el kernel y, por lo tanto, no se ejecutan subprocesos. Si los hilos son administrados por kernel, la mayoría de los kernels ejecutarán otros hilos si un hilo se bloquea. Puede ejecutar una prueba simple donde un hilo llama a un syscall repetidamente y otro produce repetidamente. Si el hilo de rendimiento obtiene algún tiempo de ejecución, significa que el syscall es un punto de preferencia. – Artelius

8

Las llamadas al kernel se consideran ya sea bloqueo o sin bloqueo . Una llamada de bloqueo (como esperar a que los datos se lean desde un socket de red) puede ser reemplazada sin que se requiera ninguna acción de su parte. Otros hilos continuarán ejecutándose. Las llamadas al kernel no bloqueantes se pueden considerar muy rápidas y, en términos prácticos, no importará si puedes anticiparlas o no.

Generalmente, cuando se escribe código multiproceso, se concentra en cómo esos hilos interactúan entre sí, y deja su interacción con el kernel hasta el kernel para administrar. Está diseñado para hacer un trabajo bastante bueno.

+0

Bueno, en este caso, estoy escribiendo una prueba para la API y los planes de prueba implican analizar lo que sucede cuando hay una interrupción HW (se puede iniciar desde Thread_2() estando en el espacio de usuario) en el medio la ejecución de la API. Así que, idealmente, me gustaría Thread_1 (_ para poder ceder en medio de la ejecución de la API, dar control a Thread_2() (iniciando una secuencia que llevaría a una interrupción HW), volviendo a Thread_1() y reanudar la ejecución: si la API puede mantener su propio/guardar estado, etc., mientras que la interrupción HW en realidad lo golpea, entonces todo está bien! – TCSGrad

+0

Es posible que desee ver el enfoque alternativo que estaba pensando en este http://stackoverflow.com/ questions/1885903/how-to-call-ac-function-from-random-places-inside-another-function. Sin embargo, puede omitirlo: ¡toda la información está aquí en esta pregunta! :) – TCSGrad

7

Eso depende del kernel. Clásicamente, los núcleos no permitían la apropiación (excepto en puntos específicos cuando dormía un hilo). Pero los kernels más nuevos han comenzado a permitir la apropiación dentro del kernel mismo.

Linux admite un núcleo apropiable cuando se genera con CONFIG_PREEMPT. A partir de la documentación del núcleo:

Esta opción reduce la latencia del núcleo haciendo todo el código del núcleo (que no se está ejecutando en una sección crítica) con derecho preferente. Esto permite la reacción a eventos interactivos por permitiendo que un proceso de baja prioridad sea apropiadamente involuntario incluso si está en modo kernel ejecutando una llamada al sistema y de lo contrario no estaría a punto de alcanzar un punto de apropiación natural. Esto permite que las aplicaciones se ejecuten de forma más "fluida" incluso cuando el sistema está bajo carga, a un costo ligeramente menor y una ligera sobrecarga de tiempo de ejecución para el código del kernel.

Seleccione esto si está creando un kernel para un escritorio o un sistema integrado con requisitos de latencia en el rango de los milisegundos .

Cuestiones relacionadas