2011-10-29 17 views
11

Le code di lavoro Linux sono pensate per essere thread a livello di kernel con contesto di processo. Stavo cercando di usarlo come alternativa a kthread che non ha un contesto di processo specifico. Ma come faccio a passare i dati alla coda di lavoro? work_struct ha un campo dati che è di tipo atomic_long_t. Non potevo passare il puntatore a questo campo. Come lo faccio?Come utilizzare Linux Work Queue

Inoltre, non sono riuscito a trovare un singolo esempio concreto di coda di lavoro. Puoi suggerirne uno?

+3

Un ottimo blog spiega tutti il ​​concetto di base kernel Linux con esempi: http://tuxthink.blogspot.co.il/2011/09 /workqueues-1-introduction.html http://tuxthink.blogspot.co.il/2011/09/workqueue-2-declarework.html http://tuxthink.blogspot.co.il/2011/09/workqueue -3-using-runtime-creation.html – 0x90

risposta

16

Se si desidera passare i dati alla propria funzione di coda di lavoro, incorporare semplicemente la struttura work_struct all'interno della propria struttura dati e utilizzare container_of all'interno della funzione di lavoro per recuperarlo.

Come per un semplice esempio, il kernel è pieno di esso - solo git grep work_struct. È possibile guardare a drivers/cpufreq/cpufreq.c (funzione handle_update) per un semplice esempio. L'articolo qui sotto inoltre incorpora un esempio alla fine, ma non utilizza container_of e invece si basa sul fatto che il primo elemento di una struttura ha lo stesso indirizzo dell'elemento superiore:

http://www.ibm.com/developerworks/linux/library/l-tasklets/index.html

+0

Grazie. Funziona e incredibilmente semplice. – max

+0

http://www.makelinux.net/ldd3/chp-7-sect-6 - passa a questo punto per una seconda lettura (solo le code di lavoro) –

0

Per default il la funzione di lavoro viene chiamata con il lavoro come parametro. All'interno del thread è possibile ottenere facilmente l'elemento dati della struttura. Anche un Gnurou, per ottenere l'accesso di più dati, la struttura di lavoro può essere inserita all'interno di una specifica struttura di implementazione e utilizzando il contenitore di macro all'interno del thread è possibile accedere a tutti i dati.

Una descrizione semplice circa WorkQueue

worqueue sono interrupt movimentazione metà inferiore mechanishm, dove una parte del lavoro è dato a un thread kernel per eseguire successivamente con preemtion su un interrupt consentono. Un thread percpu eventi/n viene creato dal kernel, i thread possono anche essere creati dal codice driver. Una struttura viene utilizzata per identificare il thread, un parametro importante all'interno della struttura è il campo nome. Inoltre contiene una struttura per CPU che in turn contiene la coda waitqueue su cui il thread attende e una lista di collegamenti per aggiungere la struttura che definisce il lavoro, cioè la funzione e i dati. Il thread worker ottiene quella struttura come parametro di input. Il thread viene eseguito e attende l'attesa per qualcuno per svegliare il thread. Viene creata una struttura di lavoro che definisce la funzione. Quando una work codeue è programmata, la struttura viene aggiunta alla coda dell'elenco di collegamenti e il thread di lavoro viene riattivato. Al risveglio, il thread worker esegue l'elenco dei collegamenti definito nella struttura per CPU e inizia ad eseguire le funzioni definite con la struttura di lavoro come parametro. Dopo l'esecuzione rimuove la voce dall'elenco dei collegamenti.

2

Sembra risolto e mi è stato di grande aiuto per capire come utilizzare le code di lavoro.Vi do un codice di un semplice esempio nel mio github, sperando che sia utile a tutti:

https://github.com/m0r3n/kernel_modules/blob/master/workQueue.c

È possibile compilare il seguente Makefile:

KVERSION = $(shell uname -r) 
obj-m = workQueue.o 

all: 
    make -C /lib/modules/$(KVERSION)/build M=$(PWD) modules 
clean: 
    make -C /lib/modules/$(KVERSION)/build M=$(PWD) clean 

Inserire il modulo da:

# sync; insmod workQueue.ko; sync 

e vedere i log:

# tailf /var/log/kern.log 

EDIT: Ho appena aggiunto la versione ritardata:

https://github.com/m0r3n/kernel_modules/blob/master/workQueueDelayed.c