2012-04-16 11 views
10

He visto fragmentos de información dispersa, pero parece que no puedo obtener una respuesta final. ¿Cómo se limpia un hilo zombie en Kernel?Manera correcta de manejar hilos en kernel?

Solo para asegurarme, y producir una forma correcta final de manejar los hilos en kernel, me gustaría hacer esta pregunta más ampliamente. ¿Cómo se crea, finaliza y limpia un hilo en el kernel de Linux?

Lo que tengo hasta ahora es la siguiente:

thread_func: 
    exited = 0; 
    while (!must_exit) 
     do stuff 
    exited = 1; 
    do_exit(0) 

init_module: 
    must_exit = 0; 
    exited = 1; 
    kthread_run(thread_func, ...) /* creates and runs the thread */ 

cleanup_module: 
    must_exit = 1; 
    while (!exited) 
     set_current_state(TASK_INTERRUPTIBLE); 
     msleep(1); 
    /* How do I cleanup? */ 

Lo más parecido que he encontrado para la solución de limpieza es release_task, pero que no encontrar en cualquier lugar de hablar de ello. Imaginaba que dado que las funciones de subprocesos son kthread_create, kthread_run etc., debería haber un kthread_join o kthread_wait, pero no lo había. do_wait también parecía probable, pero no toma un struct task_struct *.

Además, no estoy seguro de si do_exit es una buena idea, o si es necesario tampoco. ¿Puede alguien dar el boceto mínimo de cómo debe crearse, terminarse y limpiarse una kthread?

+2

Me parece recordar que hay un kthread_stop, o kthread_should_stop, algo así. –

+0

@MartinJames, de la manera en que lo entendí, o salgas de ti mismo (usando 'do_exit') o sondear' kthread_should_stop' hasta que alguien ('cleanup_module') llame a' kthread_stop'. No encontré en ninguna parte diciendo si 'kthread_stop' también limpia el hilo o no. Lo que me hace pensar es que, si las personas (en Internet) sugieren usar 'do_exit' o lo que sea, ¿no debería haber una forma de limpiar el hilo después de' do_exit'? – Shahbaz

+0

Por cierto, [esto] (http://lwn.net/Articles/65178/) es de lo que hablo cuando digo que no puedo llegar a una respuesta definitiva. Hay muchas cosas conflictivas por ahí. – Shahbaz

Respuesta

11

Una de las formas "correctas" de hacer esto es hacer que su función de hilo compruebe si es kthread_should_stop, y simplemente regrese si necesita detenerse.

No necesita llamar al do_exit, y si tiene la intención de kthread_stop desde la función de salida del módulo, probablemente no deba hacerlo.

se puede ver esto mirando la documentación para kthread_create_on_node en kernel/kthread.c (extracto de Linux kernel 3.3.1):

/** *
kthread_create_on_node - crear un kthread.
* @threadfn: la función se ejecuta hasta signal_pending (current).
* @data: datos ptr para @threadfn.
* @node: número de nodo de memoria.
* @namefmt: nombre de estilo de printf para el subproceso.
*
* Descripción: Esta función de ayuda crea y nombra un núcleo
* thread. El hilo se detendrá: use wake_up_process() para iniciar
* it. Ver también kthread_run().
*
* Si el hilo se va a unir a una CPU en particular, proporcione su nodo
* en @node, para obtener la afinidad NUMA por la pila kthread, o bien proporcione -1.
* Cuando se lo despierte, el subproceso se ejecutará @threadfn() con @data como su argumento
*. @threadfn() puede llamar do_exit() directamente si es un hilo independiente
* por el que nadie llamará kthread_stop(), o
* retorno cuando 'kthread_should_stop()' es cierto (lo que significa
* se ha llamado a kthread_stop()). El valor de retorno debe ser cero
* o un número de error negativo; se pasará a kthread_stop().
*
* Devuelve un task_struct o ERR_PTR (-ENOMEM).
*/

Una "coincidencia" comentario está presente para kthread_stop:

Si threadfn() puede llamar do_exit() sí, la persona que llama debe garantizar task_struct no puede irse.

(Y no estoy seguro de cómo se hace eso - probablemente se aferra a la struct_task con un get_task_struct.)

Si camina el camino de una creación del hilo que obtendrá algo como:

kthread_create           // macro in kthread.h 
    -> kthread_create_on_node        // in kthead.c 
    -> adds your thread request to kthread_create_list 
    -> wakes up the kthreadd_task 

kthreadd_task está configurado en init/main.c en reset_init. Se ejecuta la función kthreadd (de kthread.c)

kthreadd             // all in kthread.c 
    -> create_kthread 
    -> kernel_thread(kthread, your_kthread_create_info, ...) 

Y la función kthread sí lo hace:

kthread 
    -> initialization stuff 
    -> schedule() // allows you to cancel the thread before it's actually started 
    -> if (!should_stop) 
    -> ret = your_thread_function() 
    -> do_exit(ret) 

... Así que si your_thread_function simplemente retorna, do_exit será llamada con su valor de retorno. No es necesario que lo hagas tú mismo.

+0

Bueno, la estructura de tarea es una variable global, por lo que no puede ir a ninguna parte. Pero, ¿significa esto que si el hilo independiente llama a 'do_exit()' (y por lo tanto no debería llamar a 'kthread_stop') no necesitaría limpieza? – Shahbaz

+0

Puede ir a lugares. Si la tarea a la que hace referencia esa estructura de tarea está completamente terminada, y la ruta de salida libera la estructura de tarea, la copia que tiene en los datos de su módulo es como un puntero colgante; no puede usarlo. – Mat

+0

Y sí, si no tiene la intención de 'kthread_stop' su hilo, puede llamar a' do_exit' y se producirá una limpieza normal. _Pero_ si de algún modo tu hilo logra sobrevivir a tu módulo, estás en problemas. – Mat

Cuestiones relacionadas