View Single Post
Old 07-01-2005, 11:31   #5
ilsensine
Senior Member
 
L'Avatar di ilsensine
 
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
Esempio di kernel process

Stranamente, alcune operazioni semplici in user space (come ad esempio la lettura di un file) risultano molto più complicate se effettuate dentro al kernel. Una operazione che, con le dovute cautele, risulta ancora molto semplice è la creazione di un thread.
Un modulo di per se non è un kernel thread: quando ne vengono invocate le funzionalità, il codice viene eseguito nel contesto del chiamante (che può essere un processo utente, o chiunque altro). A volte risulta utile creare un processo apposito, esistente solo in kernel space, per effettuare con calma alcune operazioni che risulterebbe troppo oneroso eseguire in altri contesti (ad es. in contesto di interruzione, o in una sezione atomica).
Questo esempio crea un processo che stampa "tick" ogni secondo:
Codice:
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kthread.h>
#include <linux/delay.h>

static struct task_struct *ktask;

static int kt_thread(void *arg)
{
	while (!kthread_should_stop()) {
		printk(KERN_INFO "tick\n");
		msleep(1000);
	}
	return 1;
}

static int __init kt_init(void)
{
	ktask = kthread_create(kt_thread, NULL, "kthread");
	if (IS_ERR(ktask)) {
		printk(KERN_ERR "Unable to create a new kernel thread!\n");
		return PTR_ERR(ktask);
	} else
		wake_up_process(ktask);
	return 0;
}

static void __exit kt_exit(void)
{
	int ret = kthread_stop(ktask);
	printk(KERN_INFO "thread killed (retval=%d)\n", ret);
}

module_init(kt_init);
module_exit(kt_exit);

MODULE_AUTHOR("ilsensine");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("sample kernel process");
Il thread viene creato con la funzione kthread_create. A questa funzione passiamo la funzione thread, il parametro eventuale per questa funzione, ed il nome. Il processo creato verrà visualizzato tramite top insieme agli altri processi.
La kthread_create crea il processo nello stato di "sospeso"; per lanciarlo, è sufficiente "svegliarlo" con wake_up_process.
La terminazione del processo avviene invocando la kthread_stop: questa funzione è _bloccante_ fino alla terminazione del processo, e ne restituisce il valore di ritorno. Notate che il processo deve attivamente esaminare la richiesta di terminazione (kthread_should_stop).
Nota importante: tutti i segnali diretti al nuovo processo sono bloccati di default (compreso l'imbloccabile SIGKILL!). Sbloccarne alcuni è semplice, ma non entro nei dettagli ora. Notate infine che la funzione msleep non può essere interrotta da alcun segnale; se vi interessa uno sleep interrompibile, occorre usare una tecnica leggermente diversa.
Un'ultima nota riguardo questa riga:
Codice:
static struct task_struct *ktask;
La dichiarazione di una variabile globale per il driver, non inizializzata, finisce nella sezione elf .bss del modulo. Al caricamento del driver, è garantito che tutte le variabili nella .bss sono inizializzate a 0.
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al
andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12

Ultima modifica di ilsensine : 23-02-2006 alle 16:42.
ilsensine è offline