2012-04-16 16 views
10

Ho visto frammenti di informazioni sparse tutt'intorno, ma non riesco a ottenere una risposta definitiva. Come si pulisce un thread di zombi nel kernel?Modo corretto di gestire i thread nel kernel?

Giusto per essere sicuro, e produrre un modo corretto finale di gestire i thread nel kernel, vorrei fare questa domanda in modo più ampio. Come si crea, si termina e si ripulisce un thread nel kernel di Linux?

Quello che ho finora è questo:

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? */ 

La cosa più vicina che ho trovato per la soluzione di pulizia è release_task, ma non ho trovato da nessuna parte parlarne. Ho immaginato poiché le funzioni thread sono kthread_create, kthread_run ecc., Ci dovrebbe essere un kthread_join o kthread_wait, ma non c'era. do_wait sembrava anche probabile, ma non ci vuole un struct task_struct *.

Inoltre, non sono sicuro se do_exit sia una buona idea, o se del tutto necessaria. Qualcuno può per favore presentare lo schizzo minimo di come dovrebbe essere creato, terminato e ripulito un kthread?

+2

Mi sembra di ricordare che c'è un kthread_stop o kthread_should_stop, qualcosa del genere. –

+0

@MartinJames, il modo in cui ho capito, o esci tu stesso (usando 'do_exit') o sondare' kthread_should_stop' finché qualcuno ('cleanup_module') chiama' kthread_stop'. Non ho trovato da nessuna parte che dicesse se 'kthread_stop' ripulisce o meno il thread. Ciò che mi meraviglia è che, se le persone (su internet) suggeriscono di usare "do_exit" o altro, non dovrebbe esserci un modo per ripulire il thread dopo "do_exit"? – Shahbaz

+0

A proposito, [questo] (http://lwn.net/Articles/65178/) è ciò di cui parlo quando dico che non riesco a raggiungere una risposta definitiva. Ci sono molte cose contrastanti là fuori. – Shahbaz

risposta

11

Uno dei "giusti" modi per farlo è quello di controllare la funzione thread se è kthread_should_stop, e restituire semplicemente se ha bisogno di fermarsi.

Non è necessario chiamare do_exit e se si intende eseguire kthread_stop dalla funzione di uscita del modulo, probabilmente non si dovrebbe.

Si può vedere questo guardando la documentazione per kthread_create_on_node a kernel/kthread.c (estratto dal kernel di Linux 3.3.1):

/**
* kthread_create_on_node - creare un processo kthread.
* @threadfn: la funzione da eseguire fino a signal_pending (corrente).
* @ data: data ptr per @threadfn.
* @node: numero del nodo di memoria.
* @namefmt: nome in stile printf per il thread.
*
* Descrizione: questa funzione di supporto crea e nomina un thread
* thread. La discussione verrà interrotta: utilizzare wake_up_process() per avviare
* it. Vedi anche kthread_run().
*
* Se il thread deve essere associato a una particolare CPU, fornire il nodo
* in @node, per ottenere l'affinità NUMA per lo stack kthread, oppure fornire -1.
* Quando viene attivato, il thread esegue @threadfn() con @data come argomento
*. @threadfn() può o chiamare do_exit() direttamente se è un filo standalone
* per i quali non si chiamerà kthread_stop(), o
* ritorno quando 'kthread_should_stop()' è vero (che significa
* kthread_stop() è stato chiamato). Il valore restituito deve essere zero
* o un numero di errore negativo; sarà passato a kthread_stop().
*
* Restituisce un task_struct o ERR_PTR (-ENOMEM).
*/

A "matching" commento è presente per kthread_stop:

Se threadfn() può chiamare do_exit() in sé, il chiamante deve garantire task_struct non può andare via.

(E io non sono sicuro di come lo si fa - probabilmente aggrappata al struct_task con un get_task_struct.)

Se si cammina il percorso di una creazione filo si otterrà qualcosa di simile:

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 è impostato in init/main.c in reset_init. Si esegue la funzione kthreadd (da kthread.c)

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

E la funzione kthread stesso fa:

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) 

... Quindi, se your_thread_function restituisce semplicemente, do_exit sarà chiamato con il suo valore di ritorno. Non c'è bisogno di farlo da solo.

+0

Bene, la struttura del task è una variabile globale, quindi non può andare da nessuna parte. Ma questo significa che se il thread standalone chiama 'do_exit()' (e quindi non dovrebbe chiamare 'kthread_stop') non avrebbe bisogno di pulizia? – Shahbaz

+0

Può andare in posti. Se l'attività a cui si riferisce la struttura di questa attività è completa, e la struttura dell'attività viene liberata dal percorso di uscita, la copia presente nei dati del modulo è proprio come un puntatore che penzola: non è possibile utilizzarla. – Mat

+0

E sì, se non hai intenzione di 'kthread_stop' il tuo thread, può chiamare' do_exit' e la normale pulizia avverrà. _Ma_ se in qualche modo il tuo thread riesce a sopravvivere al tuo modulo, sei nei guai. – Mat