Se la funzione riceve un puntatore ai dati dello spazio utente, devi usare copy_from_user()
per copiare i dati puntati dallo spazio utente allo spazio kernel (e viceversa).
Nota che il valore del puntatore stesso viene passato per valore (come tutti i parametri C), quindi non devi fare un copy_from_user()
per ottenere il valore del puntatore prima di poter copy_from_user()
i dati a cui punta.
Gli argomenti numerici funzionano allo stesso modo degli argomenti puntatore; in termini C, sono entrambi scalari. Non devi usare copy_from_user()
copiare il valore del parametro; è già stato copiato. Devi solo usarlo per copiare i dati a cui punta un puntatore passato.
Quindi, se hai un parametro di tipo int
, puoi usarlo direttamente. Se il tuo parametro punta a un int
, quindi il int
oggetto sarà nello spazio utente e devi usare copy_to_user
per copiare il valore di quell'oggetto nello spazio del kernel.
Quando un utente passa i dati allo spazio del kernel, questi dati possono essere suddivisi su più pagine e queste pagine possono trovarsi anche nella memoria scambiata . In questi casi, dovrai attendere che il kernel effettui lo swapping nella pagina e ottenga l'accesso alla pagina in cui si trovano i dati. Nel caso di tipi di dati elementari (come int o puntatori) è anche vero che alcune architetture (in particolare x86 Intel) non obbligano l'utente ad allineare i dati in modo che anche un numero intero possa essere suddiviso attorno al bordo di una pagina. Puoi avere accesso alla prima parte del tuo numero intero, ma devi aspettare che la seconda venga scambiata dal gestore della memoria prima che si acceda all'intera cosa.
Puoi salvare alcuni roundtrip inserendo tutti i dati utente in una struttura il cui puntatore viene passato al kernel. Puoi copiarlo_da_utente come blocco e salvare gli accessi (e correre il rischio di essere bloccato più volte)
Quindi, e in conclusione, usa le funzioni anche per i tipi base , poiché ce ne sono molti. Non dare per scontato nulla su dove possono trovarsi i dati dell'utente durante l'esecuzione in modalità kernel. Puoi accedervi, ma gli indirizzi virtuali del kernel dei dati utente non hanno nulla a che fare con gli indirizzi virtuali visualizzati in modalità utente.