Esplora E-book
Categorie
Esplora Audiolibri
Categorie
Esplora Riviste
Categorie
Esplora Documenti
Categorie
"Parthenope"
Facolt di scienze e tecnologie
Corso di Laurea in Informatca
Autori:
Raffaela DAniello 0124000637
Luisa Barbarino 0124000484
Daniele Ioviero 0124000459
Fabio Nisci 0124000074
Relatore:
Prof. Alfredo Petrosino
ii
Indice
Indice
iii
iv
Introduzione
1.1
Introduzione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.2
Ruolo dei dispositivi di periferica . . . . . . . . . . . . . . . . . . . .
1.3
Kernel Linux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1
1
1
1
I Moduli
2.1
Le Classi di dispositivi e moduli . . .
2.2
Problemi di sicurezza . . . . . . . . .
2.3
Moduli caricabili . . . . . . . . . . .
2.4
I moduli di costruzione ed esecuzione
2.5
Compliazione ed esecuzione . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
4
4
4
5
5
6
Gestione e comunicazione
3.1
Modulo Kernel VS Applicazioni Utente . . . . .
3.2
Polling VS Interrupt . . . . . . . . . . . . . . .
3.3
Interrupt Handling . . . . . . . . . . . . . . . .
3.4
I/O Bloccante . . . . . . . . . . . . . . . . . . .
3.5
Chiamata di sistema da unapplicazione utente
3.6
Sleeping . . . . . . . . . . . . . . . . . . . . . .
3.7
Wait Queue . . . . . . . . . . . . . . . . . . . .
3.8
System call Select/Poll . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
8
8
9
9
10
10
11
11
12
14
14
Debug
18
iii
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
5.1
iv
18
Linux Kernel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.1
3.2
device_open() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
device_poll() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
10
12
Capitolo 1
Introduzione
1.1
Introduzione
Uno dei molti vantaggi del Sistema Operativo Linux che il suo interno aperto a tutti.
Il kernel Linux un corpo grande e complesso di codice. I drivers di periferica, sono distinte
scatole nere che fanno s che un particolare pezzo di hardware risponda ad un interfaccia
di programmazione ben definita. Le attivit dellutente sono effettuate tramite una serie
di chiamate standardizzate indipendenti dal driver specifico. Quindi i driver possono essere
costruiti separatamente dal resto del kernel e inseriti a runtime quando necessario.
1.2
Come programmatore, si in grado di fare le proprie scelte circa il driver, e scegliere un accettabile compromesso tra il tempo di programmazione richiesto e la flessibilit del risultato,
ovvero il ruolo di un driver di periferica fornisce il meccanismo, non la politica. La maggior parte dei problemi di programmazione possono infatti essere divise in due parti: quali
funzionalit devono essere forniti (il meccanismo) e come possono essere utilizzate quelle
capacit (la politica). Esempio, la gestione Unix del display grafico diviso tra il server
X, che conosce lhardware e offre uninterfaccia unificata per programmi utente, e il gestore
delle finestre e di sessione, che implementano una particolare politica senza sapere nulla
lhardware. Gli utenti possono utilizzare lo stesso gestore di finestre su hardware diversi, e
viceversa diversi utenti possono eseguire diverse configurazioni sulla stessa workstation.
inoltre possibile guardare il driver da una prospettiva diversa: si tratta di uno strato di software che si trova tra le applicazioni e il dispositivo vero e proprio. Caratteristiche tipiche:
Queste includono il supporto per entrambi funzionamento sincrono e asincrono, la capacit
di essere aperto pi volte, la capacit di sfruttare tutte le funzionalit dellhardware, e la
mancanza di strati di software a semplificare le cose o fornire le operazioni legate alla
politica.
1.3
Kernel Linux
Gestione dei processi: Il kernel si occupa della creazione e distruzione dei processi,
della loro comunicazione.
CAPITOLO 1. INTRODUZIONE
Gestione della memoria: Le varie parti del kernel interagiscono con il sottosistema di
gestione della memoria attraverso una serie di chiamate di funzione, che vanno dal
semplice malloc ad altre pi complesse.
Filesystem: quasi tutto in Unix pu essere trattato come un file. Il kernel costruisce un
file system strutturato in cima hardware non strutturato, e la conseguente estrazione
di file molto utilizzato in tutto il sistema.
Controllo dispositivi funzionamento: a quasi tutti i sistemi associato un dispositivo
fisico. Con leccezione del processore, memoria e poche altre entit, qualsiasi e tutte le
operazioni di controllo del dispositivo vengono eseguite da codice (Driver di periferia)
che specifico per il dispositivo. Il kernel deve avere incorporato un device driver per
ogni periferica presente sul sistema, dal disco rigido alla tastiera e lunit a nastro.
Networking: deve essere gestita dal sistema operativo, perch la maggior parte delle
operazioni di rete non sono specifici di un processo: i pacchetti in ingresso sono eventi
asincroni. I pacchetti devono essere raccolti, identificati e spediti prima che un processo
si prenda cura di loro. Inoltre, tutti i problemi di risoluzione di routing e di indirizzo
sono implementati allinterno del kernel.
CAPITOLO 1. INTRODUZIONE
Capitolo 2
I Moduli
2.1
2.2
Problemi di sicurezza
Nella distribuzione ufficiale del kernel, solo un utente autorizzato pu caricare moduli; la
chiamata di sistema init_module controlla se il processo chiamante autorizzato a caricare
un modulo nel kernel.
CAPITOLO 2. I MODULI
2.3
Moduli caricabili
2.4
/*
* " Hello , world !" minimal kernel module
*
* Fabio Nisci < f a b i o n i s c i @ s t u d e n t i . uniparthenope . it >
*
*/
7
9
11
13
/*
* The below are header files provided by the kernel which are
* required for all modules . They include things like the definition
* of the module_init () macro .
*/
# include < linux / init .h >
# include < linux / module .h >
15
17
19
/*
* This is the init function , which is run when the module is first
* loaded . The __init keyword tells the kernel that this code will
* only be run once , when the module is loaded .
*/
21
23
25
27
29
31
33
module_init ( hello_init ) ;
35
37
39
/*
* Similary , the exit function is run once , upon module unloading , and
* the module_exit () macro identifies which function is the exit
* function .
*/
41
43
CAPITOLO 2. I MODULI
{
printk ( " Goodbye , world !\ n " ) ;
45
}
47
module_exit ( hello_exit ) ;
49
51
53
55
57
59
61
/*
* MODULE _LICEN SE () informs the kernel what license the module source
* code is under , which affects which symbols it may access in the
* main kernel . Certain module licenses will " taint " the kernel ,
* indicating that non - open or untrusted code has been loaded .
* Modules licensed under GPLv2 do not taint the kernel and can access
* all symbols , but declaring it so is a legal statement that the
* source code to this module is licensed under GPLv2 , and so you must
* provide the source code if you ship a binary version of the module .
*/
MODU LE_LIC ENSE ( " GPL " ) ;
M O D U L E _ D E S C R I P T I O N ( " \" Hello , world !\" minimal module " ) ;
MODU LE_VER SION ( " printk " ) ;
Spiegazione:
Questo modulo definisce due funzioni, una per essere invocata quando il modulo caricato
nel kernel (hello_init) e una per quando il modulo viene rimosso (hello_exit). Le linee
module_init e module_exit utilizzano macro speciali del kernel per indicare il ruolo di
queste due funzioni. Unaltra macro speciale (MODULE_LICENSE) utilizzato per dire
al kernel che questo modulo ha una licenza gratuita; senza una tale dichiarazione, il kernel si
lamenta quando viene caricato il modulo. La funzione printk definita nel kernel di Linux e
messo a disposizione moduli; si comporta in modo simile alla funzione printf della libreria C
standard. Il kernel ha la propria funzione di stampa perch corre da sola, senza laiuto della
libreria C. Il modulo pu chiamare printk perch, dopo insmod il modulo legato al kernel e
pu accedere simboli pubblici del kernel (funzioni e variabili, come dettagliato nella sezione
successiva). Il KERN_ALERT indica la priorit del messaggio. Abbiamo specificato la
massima priorit in questo modulo, perch un messaggio con la priorit predefinita potrebbe
non presentarsi ovunque utile, a seconda della versione del kernel in esecuzione, la versione
del klogd daemon, e la configurazione. possibile ignorare questo problema, per ora.
possibile verificare il modulo con la insmod e rmmod utilities, come illustrato di seguito.
Notare che solo il superuser pu caricare e scaricare un modulo.
2.5
Compliazione ed esecuzione
Listing 2.2: "Makefile"
obj - m := hello_printk . o
6
8
10
12
CAPITOLO 2. I MODULI
14
PWD
16
18
20
:= $ ( shell pwd )
target . The rule here says to run make
the directory containing the kernel
modules in the PWD ( local ) directory .
modules
Spiegazione: Si prega di notare ancora una volta che, per questa sequenza di comandi,
necessario disporre di un kernel configurato correttamente e costruita in un luogo dove
il makefile in grado di trovarlo (/usr/src/linux2.6.10 nellesempio mostrato). Otteniamo
nei dettagli di come i moduli sono costruiti nella sezione Compilazione e caricamento. A
Seconda del meccanismo che il sistema utilizza per fornire le linee di segnalazione, loutput
potrebbe essere diverso. In particolare, la schermata precedente stata presa da una console
di testo; se si esegue insmod e rmmod da un emulatore di terminale in esecuzione con il
sistema a finestre, non vedrete nulla sul vostro schermo. Il messaggio va a uno dei file
di registro di sistema, come /var /log /messaggi (il nome del file effettivo varia tra le
distribuzioni Linux. Come potete vedere, la scrittura di un modulo non cos difficile come
si potrebbe aspettare, almeno, fino a quando il modulo non tenuto a fare qualcosa di
utile. La parte difficile capire il vostro dispositivo e su come ottimizzare le prestazioni.
Andiamo pi a fondo la modularizzazione in questo capitolo e lasciare i problemi specifici
del dispositivo per i capitoli successivi.
Capitolo 3
Gestione e comunicazione
3.1
3.2
Polling VS Interrupt
Il polling e le interrupt sono due modi per far comunicare il processore ed il dispositivo.
Ricordiamo che il polling la verifica ciclica di tutte le unit/periferiche da parte del SO;
continuiamo a leggere la porta usando istruzioni continuamente finch non arrivano dati con
cui lavorare. Questo modo di ricezione dei dati pu essere appropriato solo per dispositivi
che hanno un I/O ad alta velocit. Questo perch arrivano molti dati velocemente e il
processore deve rimanere al passo. Quando, invece, abbiamo a che fare con dispositivi pi
lenti o in cui non ci si aspetta che i dati arrivino continuamente, una interrupt sar molto
pi appropriata, altrimenti con il polling sprecheremmo molti cicli di CPU controllando la
porta inutilmente. Una interrupt asincrona perch non sappiamo quando arriver levento
che la richiamer; basata sul bisogno del dispositivo, cio vogliamo che a prescindere dal
flusso dei dati il processore riesca a gestirli tutti Consideriamo unapplicazione utente il cui
scopo quello di suonare un allarme se il sensore che legge i dati in input legge valori in un
dato range. Diciamo che quando ci troviamo in quel range vogliamo agire in qualche modo
sui dati, ma non sappiamo quando questa situazione accadr e le operazioni del dispositivo
sono molto pi lente rispetto a quelle del processore. In questo caso luso di una interrupt
pi appropriato cos da non controllare sempre in polling, ma gestire linterrupt solamente
quando levento accade.
3.3
Interrupt Handling
Una interrupt un segnale che lhardware pu inviare per ottenere lattenzione del processore. Abbiamo spiegato come le interrupt sono gestite dal processore. Le interrupt del
processore sono gestite dal IRS (interrupt routine service). Tali routine sono essenzialmente
programmi che il processore deve eseguire allaccadere delle interrupt. Quindi allaccadere dellinterrupt dal dispositivo bisogna eseguire delle azioni. Lammontare di tali azioni
dipende dal dispositivo. Ci sono delle restrizione dellISR:
1. esso non eseguito nel contesto di un processo. Sappiamo che il SO pu gestire pi
processi/thread di tipo utente, ma quando ci troviamo in spazio kernel non abbiamo
tante informazioni sui processi/thread di tipo kernel e il loro contesto rispetto a quelli
utente; lISR non eseguito nello spazio utente, ma esso parte del SO quindi non
possiamo trasferire dati da/a lo spazio utente.
2. il processore non DEVE dormire quando nellISR. NellISR possiamo avere system
call, ma queste non possono essere bloccanti, cio non possiamo eseguire chiamate
come la wait_event, bloccare un semaforo/scheduler, etc. perch queste chiamate di
sistema potrebbero mettere lintero SO in stato sleep. Possiamo lasciare processi
utente dormire, ma non una buona idea per processi kernel.
Il ruolo dellISR:
da feedback al dispositivo sulla ricezione dellinterrupt (tramite la pulizia di un flag)
lettura/scrittura dei dati tipicamente avviene qui
pulizia dellINTERRUPT BIT
risveglia processi dormienti sul dispositivi in attesa di qualche evento
3.4
10
I/O Bloccante
3.5
11
dispositivo. I moderni kernel di Linux associano molti dispositivi allo stesso major number.
Il minor number e; usato dal kernel per determinare esattamente a quale dispositivo ci si
sta riferendo. In base a come scritto il driver possiamo ottenere o il puntatore diretto al
dispositivo dal kernel o usare il minor number come indice in un array di dispositivi. Proprio
grazie alla coppia minus+major number il kernel sar in grado di identificare il file e linkarlo
al modulo kernel mydriver. Una read allinterno dellapplicazione utente sar collegata ad
una funzione del modulo kernel grazie alla struttura file_operations che fa corrispondere
la .read a device_read. A questo punto controlliamo la lunghezza del buffer, se ci sono
dati disponibili; se tutto ok faccio la copy_to_user (API del kernel) cosicch i dati sul
dispositivo vengano inviati al processo utente tramite il buffer. Altrimenti se non abbiamo
dati in entrata allora mettiamo lapplicazione utente a dormire.
3.6
Sleeping
Cosa vuol dire che un processo sta dormendo? Noi sappiamo che sistema operativo usa lo
scheduler per dare un tipo di ordinamento al susseguirsi dei processi o dei thread, avvalendosi
dellutilizzo di una coda. Sappiamo che gli stati dei processi sono diversi, tra cui troviamo
lo stato sleeping. Un processo che si trova nello stato sleeping, vuol dire che viene rimosso
dalla coda di esecuzione dello scheduler. finch qualche evento futuro non cambia lo stato, il
processo non sar in scheludato sulla CPU e, di conseguenza, non verr eseguito. Per far s
che un processo vada nello stato sleeping in modo sicuro, bisogna osservare un paio di regole
importanti. La prima regola che non bisogna mai passare allo stato sleeping quando
ci si trova in un contesto atomico (fetch decode execute). Ricordiamo che un contesto
atomico si ha quando diverse operazioni devono essere eseguite senza alcun tipo di accesso
concorrente. La seconda regola da osservare che non possibile impostare lo stato sleeping
se gli interrupt sono disabilitati. Una cosa da ricordare e che quando si sveglia un processo
dallo Stato sleeping, non possiamo sapere quanto tempo rimasto fuori dalla CPU e ci
che, nel frattempo, pu essere cambiato. Un altro punto rilevante che un processo non
pu dormire finch non si assicurato che qualche altro processo, da qualche altra parte,
possa risvegliarsi.
3.7
Wait Queue
Abbiamo prima menzionato lutilizzo di una coda. La coda delle attese una struttura
kernel, ed una lista dei processi in attesa di uno specifico evento. Con questa struttura delle code di attesa, il kernel ha la possibilit di trovare i processi dormienti nel caso
in cui, nel prossimo futuro, decide di risvegliarli. Il driver di un qualsiasi device pu utilizzare questa struttura, e pu anche creare una specifica coda ed utilizzarla per i propri
scopi. La coda delle attese gestita da una struttura chiamata wait queue head e definita nel file <wait.h>. una struttura molto semplice, composta da spinlock ed una
linked list. Questa struttura contiene informazioni relative al processo dormiente ed inoltre a come si vorrebbe essere svegliati. La wait queue pu essere definita e inizializzato
staticamente con DECLARE_WAIT_QUEUE_HEAD (nome) oppure dinamicamente con
wait_queue_head_t nome_coda e init_waitqueue_head (& nome_coda);
3.8
12
Le applicazioni che usano lI/O non bloccante, spesso usano le chiamate di sistema poll,
select ed poll. Queste chiamate di sistema permettono ad un processo di determinare se
possibile leggere o scrivere su uno o pi file aperti senza bloccare nulla. Queste chiamate di
sistema possono anche bloccare un processo finch un descrittore di file diventa disponibile
per la lettura o scrittura. Poll/Select vengono spesso richiamate in applicazioni che devono
utilizzare pi flussi di ingresso o uscita senza restare bloccati su uno di questi. La chiamata
di sistema poll stata aggiunta per ampliare la scala della funzione polling, agendo su
migliaia descrittori di file. Per utilizzare queste chiamate di sistema necessario il supporto
del driver del device, coinvolgendo quindi, un descrittore di file associato al driver. Se
guardiamo questo codice esempio:
13
vo, ma nella maggior parte dei casi ci avvaliamo delle interrupt per risvegliare i processi.
Il blocco arancione mette in risalto la IRS che risveglia il processo. La wake_up avr
bisogno dellelemento della wait queue da risvegliare e il processo riprender lesecuzione.
Capitolo 4
Costruiamo un driver
Il driver che costruiremo appartiene alla classe dei character devices. Il dispositivo implementa la lettura/scrittura di un carattere. Anche non essendo molto utile ai fini pratici,
fornisce un valido esempio sul funzionamento completo di un driver. semplice da implementare, in quanto non si interfaccia a nessun dispositivo hardware reale (oltre che al
computer stesso).
Listing 4.1: "Modulo Char Device"
2
4
/*
* chardev . c : Creates a read - only char device that says how many times
* you ve read from the dev file
* Host : Fabio Nisci < f a b i o n i s c i @ g m a i l . com >
*/
6
8
10
12
14
16
18
20
22
24
26
28
30
# include
# include
# include
# include
/*
* Prototypes - this would normally go in a . h file
*/
int init_module ( void ) ;
void cleanu p_modu le ( void ) ;
static int device_open ( struct inode * , struct file *) ;
static int dev ice_re lease ( struct inode * , struct file *) ;
static ssize_t device_read ( struct file * , char * , size_t , loff_t *) ;
static ssize_t device_write ( struct file * , const char * , size_t , loff_t *) ;
# define SUCCESS 0
# define DEVICE_NAME " chardev " /* Dev name as it appears in / proc / devices
*/
# define BUF_LEN 80
/* Max length of the message from the device */
/*
* Global variables are declared as static , so are global within the file .
*/
static int Major ;
/* Major number assigned to our device driver */
static int Device_Open = 0; /* Is device open ?
14
32
34
36
38
40
42
44
46
48
/*
* This function is called when the module is loaded
*/
int init_module ( void )
{
Major = r e gi st e r_ ch r de v (0 , DEVICE_NAME , & fops ) ;
if ( Major < 0) {
printk ( KERN_ALERT " Registering char device failed with % d \ n " , Major ) ;
return Major ;
}
50
52
54
printk ( KERN_INFO
printk ( KERN_INFO
printk ( KERN_INFO
printk ( KERN_INFO
printk ( KERN_INFO
printk ( KERN_INFO
56
58
60
return SUCCESS ;
62
}
64
66
68
70
72
74
/*
* This function is called when the module is unloaded
*/
void cleanu p_modu le ( void )
{
/*
* Unregister the device
*/
u n r e g i s t e r _ c h r d e v ( Major , DEVICE_NAME ) ;
printk ( KERN_INFO " U n r e g i s t e r _ c h r d e v " ) ;
}
76
78
/*
* Methods
*/
80
82
84
86
/*
* Called when a process tries to open the device file , like
* " cat / dev / mycharfile "
*/
static int device_open ( struct inode * inode , struct file * file )
{
static int counter = 0;
88
90
if ( Device_Open )
return - EBUSY ;
92
Device_Open ++;
15
sprintf ( msg , " I already told you % d times Hello world !\ n " , counter ++) ;
msg_Ptr = msg ;
try _modul e_get ( THIS_MODULE ) ;
94
96
return SUCCESS ;
98
100
102
104
}
/*
* Called when a process closes the device file .
*/
static int dev ice_re lease ( struct inode * inode , struct file * file )
{
Device_Open - -;
/* We re now ready for our next caller */
106
/*
* Decrement the usage count , or else once you opened the file , you ll
* never get get rid of the module .
*/
module_put ( THIS_MODULE ) ;
108
110
112
return 0;
114
116
/*
* Called when a process , which already opened the dev file , attempts to
* read from it .
*/
static ssize_t device_read ( struct file * filp , /* see include / linux / fs . h
*/
char * buffer , /* buffer to fill with data */
size_t length , /* length of the buffer
*/
loff_t * offset )
{
/*
* Number of bytes actually written to the buffer
*/
int bytes_read = 0;
118
120
122
124
126
128
130
132
134
/*
* If we re at the end of the message ,
* return 0 signifying end of file
*/
if (* msg_Ptr == 0)
return 0;
136
138
140
/*
* Actually put the data into the buffer
*/
while ( length && * msg_Ptr ) {
/*
* The buffer is in the user data segment , not the kernel
* segment so "*" assignment won t work . We have to use
* put_user which copies data from the kernel data segment to
* the user data segment .
*/
put_user (*( msg_Ptr ++) , buffer ++) ;
142
144
146
148
length - -;
bytes_read ++;
150
152
16
17
/*
* Most read functions return the number of bytes put into the buffer
*/
return bytes_read ;
154
156
158
160
/*
* Called when a process writes to dev file : echo " hi " > / dev / hello
*/
static ssize_t
device_write ( struct file * filp , const char * buff , size_t len , loff_t * off )
{
printk ( KERN_ALERT " Sorry , this operation isn t supported .\ n " ) ;
return - EINVAL ;
}
162
164
166
168
Capitolo 5
Debug
5.1
GDB in grado di rilevare quando un modulo viene caricato sul target. Quindi carica il
file modulo oggetto modulo nella memoria di GDB per ottenere le informazioni di debug. Il
percorso di ricerca in cui GDB individua file di modulo si trova nella variabile solib-searchpath.
Sul target carichiamo il modulo:
target# insmod my_module.ko
Sullhost carichiamo i simboli del modulo ed impostiamo i breakpoint:
host% sh4-linux-gdb vmlinux
GNU gdb 6.3
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License,
and you are welcome to change it and/or distribute copies of it
under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.
Type "show warranty" for details.
This GDB was configured as "--host=i686-pc-linux-gnu --target=sh4-linux"...
0x84031f10 in ?? ()
Automatically enabled KGDB extensions...
(gdb) set solib-search-path /user/my_module_2.6/
Reading symbols from /user/my_module_2.6/my_mod.ko...
expanding to full symbols...done.
Loaded symbols for /user/my_module_2.6/my_mod.ko
(gdb) info sharedlibrary
From To Syms Read Shared Object Library
0xc0168000 0xc01680c0 Yes /user/my_module_2.6/my_mod.ko
(gdb) b mod_stm_open
Breakpoint 1 at 0xc0168002: file /user/my_module_2.6/my_mod.c, line 43.
(gdb) c
Continuing.
18
CAPITOLO 5. DEBUG
19
Al fine di individuare i simboli dei moduli caricabili, GDB deve essere collegato alla porta
(in cui sono stati caricati i moduli). Ci significa che il comando set solib-search-path /user/
my_module_2.6/deve essere eseguito dopo che GDB si sia connesso al target, altrimenti
raccoglie i simboli, ma non sa dove si trovano. Questo problema pu essere risolto utilizzando
i punti di interruzione in sospeso. I problemi potrebbero verificarsi anche quando lo scarico
dei moduli se GDB ha ancora i punti di interruzione allinterno del modulo. Ad esempio,
se si scarica un modulo (utilizzando il comando rmmod),senza rimuovere tutti i punti di
interruzione rilevanti in GDB, qualsiasi tentativo di avviare una nuova sessione di debug
(ad esempio fermare lesecuzione del kernel con Ctrl + C) provoca il blocco del sistema .
Questo perch KGDB stato chiesto di eseguire azioni su punti di interruzione attivi che
non sono pi accessibili.