printk() è per il kernel ciò che printf() è per lo spazio utente. Le righe scritte da printk() possono essere visualizzate tramite il comando dmesg. A seconda dell'importanza del messaggio che devi stampare, puoi scegliere tra otto messaggi a livello di log, definiti in include/linux/kern_levels.h, insieme al loro significato.
La sintassi di printk è:
printk ("log level" "message", <arguments>);
Quello che segue è un elenco dei livelli di log del kernel. Ciascuno di questi livelli corrisponde a un numero in una stringa, la cui priorità è inversamente proporzionale al valore del numero. Ad esempio, 0 ha la priorità più alta:
#define KERN_EMERG "<0>" /* system is unusable*/ #define KERN_ALERT "<1>" /* action must be taken immediately*/ #define KERN_CRIT "<2>" /* critical conditions*/ #define KERN_ERR "<3>" /* error conditions*/ #define KERN_WARNING "<4>" /* warning conditions*/ #define KERN_NOTICE "<5>" /* normal but significant condition*/ #define KERN_INFO "<6>" /* informational*/ #define KERN_DEBUG "<7>" /* debug-level messages*/
Possiamo vedere che ogni livello di log corrisponde a un numero e più basso è il numero maggiore è l'importanza del messaggio. I livelli sono utili per decidere cosa dovrebbe essere mostrato all'utente sulla console e cosa non dovrebbe esserlo.
Ogni console ha un livello di registro chiamato livello di registro della console e qualsiasi messaggio con un numero di livello di registro inferiore al livello di registro della console viene visualizzato sulla console e vengono registrati altri messaggi con un numero di livello di registro superiore o uguale al livello di registro della console nel log del kernel che può essere esaminato usando il comando “dmesg”.
Il loglevel della console può essere trovato esaminando il file /proc/sys/kernel/printk.
$ cat /proc/sys/kernel/printk 4 4 1 7
Il primo numero nell'output è il livello di registro della console, il secondo è il livello di registro predefinito, il terzo è il livello di registro minimo e il quarto è il livello di registro massimo.
Il livello di registro 4 corrisponde a KERN_WARNING. Pertanto tutti i messaggi con livelli di registro 3,2,1 e 0 verranno visualizzati sullo schermo e registrati e i messaggi con livelli di registro 4,5,6,7 verranno solo registrati e possono essere visualizzati utilizzando "dmesg".
Il livello di log della console può essere modificato scrivendo nella voce proc:
$ echo "6" > /proc/sys/kernel/printk $ cat /proc/sys/kernel/printk 6 4 1 7
Ora il livello di registro della console è impostato su 6, che è KERN_INFO. Possiamo testare la registrazione utilizzando il modulo seguente.
# vi hello.c: #include<linux/kernel.h> #include<linux/module.h> #include<linux/init.h> static int hello_init(void) { printk(KERN_WARNING "Hello, world \n "); return 0; } static void hello_exit(void) { printk(KERN_INFO "Goodbye, world \n"); } module_init(hello_init); module_exit(hello_exit);
Il printk chiamato nella funzione init usa KERN_WARNING che è il livello di log e minore di 6 che è il livello di log della console e quindi dovrebbe essere visto sullo schermo.
Il printk utilizzato nella funzione di uscita è KERN_INFO che è log level 6, lo stesso del log level della console, e quindi non dovrebbe essere visibile sullo schermo.
Nota :Possiamo testare il funzionamento del codice solo accedendo a una modalità testo poiché nessuno dei messaggi viene visualizzato su un terminale della GUI.Makefile:
ifneq ($(KERNELRELEASE),) obj-m := hello.o else KERNELDIR ?= /lib/modules/$(shell uname -r)/build PWD := $(shell pwd) default: make -C $(KERNELDIR) M=$(PWD) modules clean: $(MAKE) -C $(KERNELDIR) M=$(PWD) clean endif
Compila e inserisci:
$ make $ insmod hello.ko [5377.966743] Hello world
Possiamo vedere il Hello World stampato sullo schermo.
$ rmmmod hello $ dmesg| tail -2 [5424.190552] Good bye world
Il messaggio di arrivederci al mondo viene registrato ma non viene stampato sullo schermo ma può essere visualizzato nei registri. Quindi usando printk e i livelli di log della console possiamo controllare i messaggi del kernel visibili all'utente.
Pensieri finali
Il kernel usa la funzione printk, che è molto simile sintatticamente alla chiamata alla funzione printf delle librerie C standard, con l'aggiunta di un livello di log opzionale. I formati consentiti sono documentati nel sorgente del kernel in Documentation/printk-formats.txt.
I livelli di log disponibili in printk sono presentati nella tabella seguente:
Tipo | Simbolo | Descrizione |
---|---|---|
Emergenza | KERN_EMERG | Il sistema è instabile e sta per arrestarsi in modo anomalo |
Avviso | KERN_ALERT | È necessaria un'azione immediata |
Critico | KERN_CRIT | Guasto software o hardware critico |
Errore | KERN_ERR | Condizione di errore |
Avviso | KERN_WARNING | Niente di grave, ma potrebbe indicare un problema |
Avviso | KERN_NOTICE | Niente di grave, ma l'utente dovrebbe prenderne nota |
Informazioni | INFO_KERN | Informazioni di sistema |
Debug | KERN_DEBUG | Messaggi di debug |
Se non viene specificato alcun livello di registro, viene utilizzato il messaggio di registro predefinito come configurato nella configurazione del kernel. Per impostazione predefinita, questo è KERN_WARNING.