PrerequisitosPrimer Ejemplo
Registro y parametrosScript de Instalacion, No mayor
Poniendo al proceso a dormirManejando Interrupciones
Linux Devices DriversDesarrollo de un char device
Alejandro Furfaro
Noviembre 2010
Alejandro Furfaro Linux Devices DriversDesarrollo de un char device
PrerequisitosPrimer Ejemplo
Registro y parametrosScript de Instalacion, No mayor
Poniendo al proceso a dormirManejando Interrupciones
Agenda
1 Prerequisitos.
2 Primer Ejemplo.
3 Registro y funcionalidades.
4 Script de Instalacion, No mayor
5 Poniendo al proceso a dormir
6 Manejando Interrupciones
Alejandro Furfaro Linux Devices DriversDesarrollo de un char device
PrerequisitosPrimer Ejemplo
Registro y parametrosScript de Instalacion, No mayor
Poniendo al proceso a dormirManejando Interrupciones
¿Que tenemos que instalar antes de empezar?Instalando los headers del kernel¿Que mas?
Linux Headers
Dijimos que un driver es codigo de kernel.En consecuencia, un diver va a invocar funciones internasdel kernel, y utilizara sus esctructuras de datos.Necesitamos contar con las definiciones de los prototiposde estas funciones, y estructuras. ¿Donde encontramosestas definiciones?
Alejandro Furfaro Linux Devices DriversDesarrollo de un char device
PrerequisitosPrimer Ejemplo
Registro y parametrosScript de Instalacion, No mayor
Poniendo al proceso a dormirManejando Interrupciones
¿Que tenemos que instalar antes de empezar?Instalando los headers del kernel¿Que mas?
Linux headers
En los headers del sistema operativoLos fuentes del Sistema Operativo proporcionan en susarchivos headers, las definiciones de prototipos de funciones yde estructuras de datos, que emplea el kernel. Y son las queempleara nuestro device driver. Por lo tanto hay que instalar losheaders.
Alejandro Furfaro Linux Devices DriversDesarrollo de un char device
PrerequisitosPrimer Ejemplo
Registro y parametrosScript de Instalacion, No mayor
Poniendo al proceso a dormirManejando Interrupciones
¿Que tenemos que instalar antes de empezar?Instalando los headers del kernel¿Que mas?
Version exacta
Para saber exactamente que version de kernel tenemosinstalada en el sistema, el comando uname es la respuesta:˜ $ uname −r2.6.26−1−686˜ $
Usando la propiedad de encerrar un comando entre ‘ ‘˜ $ sudo apt−get i n s t a l l l i nux−headers− ‘uname −r ‘
Alejandro Furfaro Linux Devices DriversDesarrollo de un char device
PrerequisitosPrimer Ejemplo
Registro y parametrosScript de Instalacion, No mayor
Poniendo al proceso a dormirManejando Interrupciones
¿Que tenemos que instalar antes de empezar?Instalando los headers del kernel¿Que mas?
Ya tenemos los headers ¿y ahora?
˜ $ sudo apt−get i n s t a l l l i nux−manual
E instalamos las man pages del kernel, en dondeecontraremos las funciones internas del kernel mas comunes.Mucas otras habra que rebuscar en otros medios.˜ $ sudo apt−get i n s t a l l kernel−i n t e r n a l−guide
Alguna doc, adicional del kernel.˜ $ sudo apt−get i n s t a l l ‘ ‘ L inux Device Dr ivers−3er . Ed ic i on−Alessandro Rubini− Ed . O’ r r e i l y ’ ’
:) Faltarıa que lo incluyan en el repo. “El libro” para aprender aprogramar drivers.
Alejandro Furfaro Linux Devices DriversDesarrollo de un char device
PrerequisitosPrimer Ejemplo
Registro y parametrosScript de Instalacion, No mayor
Poniendo al proceso a dormirManejando Interrupciones
Tiny exampleManos a la obra
includes y macros
#include < l i n u x / module . h>#include < l i n u x / i n i t . h>#include < l i n u x / ke rne l . h> /∗ p r i n t k ( ) ∗ //∗ ∗∗Macro que dec lara e l au tor de l modulo∗ ∗ /
MODULE AUTHOR( ” Fulano−de−t a l ” ) ;/∗ ∗∗Macro que dec lara e l t i p o de l i c e n c i a de l modulo .∗ ∗ /MODULE LICENSE( ” Dual BSD/GPL” ) ;
Alejandro Furfaro Linux Devices DriversDesarrollo de un char device
PrerequisitosPrimer Ejemplo
Registro y parametrosScript de Instalacion, No mayor
Poniendo al proceso a dormirManejando Interrupciones
Tiny exampleManos a la obra
init y exit (muy basicos)
i n t h e l l o i n i t ( void ){
p r i n t k (KERN INFO ” Hola mundo\n ” ) ;return 0;
}
void h e l l o e x i t ( void ){
p r i n t k (KERN INFO ”Chau mundo ! ! ! \ n ” ) ;}
m o d u l e i n i t ( h e l l o i n i t ) ;modu le ex i t ( h e l l o e x i t ) ;
Alejandro Furfaro Linux Devices DriversDesarrollo de un char device
PrerequisitosPrimer Ejemplo
Registro y parametrosScript de Instalacion, No mayor
Poniendo al proceso a dormirManejando Interrupciones
Tiny exampleManos a la obra
Makefile
obj−m := h e l l o . oKERNELDIR ?= / l i b / modules / $ ( s h e l l uname −r ) / b u i l dPWD := $ ( s h e l l pwd)
d e f a u l t :$ (MAKE) −C $ (KERNELDIR) M=$ (PWD) modules
clean :rm h e l l o .mod. c h e l l o . o modules . orderrm h e l l o . ko h e l l o .mod. o Module . symvers
Alejandro Furfaro Linux Devices DriversDesarrollo de un char device
PrerequisitosPrimer Ejemplo
Registro y parametrosScript de Instalacion, No mayor
Poniendo al proceso a dormirManejando Interrupciones
Tiny exampleManos a la obra
compilando...
1 Necesitamos solamente los archivos hello.c anterior yMakefile.˜ / DeviceDriverK2 . 6 / he l l o$ l s −l st o t a l 84 −rw−r−−r−− 1 a le jandro a le jandro 589 oct 19 2009 h e l l o . c4 −rw−r−−r−− 1 a le jandro a le jandro 246 nov 2 15:33 Makef i le˜ / DeviceDriverK2 . 6 / he l l o$
2 ¿Compilamos?˜ / DeviceDriverK2 . 6 / he l l o$ sudo make[ sudo ] password for a le jandro :make −C / l i b / modules/2.6.26−1−686/ b u i l d M=/home / a le jandro / DeviceDriverK2 . 6 / h e l l o modulesmake [ 1 ] : se ingresa a l d i r e c t o r i o ‘ / usr / s rc / l i nux−headers−2.6.26−1−686’
CC [M] / home / a le jandro / DeviceDriverK2 . 6 / h e l l o / h e l l o . oBu i l d i ng modules , stage 2.MODPOST 1 modulesCC / home / a le jandro / DeviceDriverK2 . 6 / h e l l o / h e l l o .mod. oLD [M] / home / a le jandro / DeviceDriverK2 .6 /2009 / h e l l o / h e l l o . ko
make [ 1 ] : se sa le de l d i r e c t o r i o ‘ / usr / s rc / l i nux−headers−2.6.26−1−686’˜ / DeviceDriverK2 . 6 / he l l o$
3 Listar el directorio y ver los archivos que se generaron.Alejandro Furfaro Linux Devices DriversDesarrollo de un char device
PrerequisitosPrimer Ejemplo
Registro y parametrosScript de Instalacion, No mayor
Poniendo al proceso a dormirManejando Interrupciones
Registrando el dispositivoCapabilitiesPasando parametros al driver
haciendo cosas utiles en init y exit
i n t h e l l o i n i t ( void ){
i n t r e s u l t ;r e s u l t = r e g i s t e r c h r d e v ( he l lo ma jo r , ” he l l o2 ” ,& h e l l o f o p s ) ;p r i n t k (KERN INFO ” he l l o2 : e l numero mayor es %d\n ” , r e s u l t ) ;he l l o ma jo r = r e s u l t ;return 0;
}void h e l l o e x i t ( void ){
unreg i s te r ch rdev ( he l lo ma jo r , ” he l l o2 ” ) ;}m o d u l e i n i t ( h e l l o i n i t ) ;modu le ex i t ( h e l l o e x i t ) ;
Alejandro Furfaro Linux Devices DriversDesarrollo de un char device
PrerequisitosPrimer Ejemplo
Registro y parametrosScript de Instalacion, No mayor
Poniendo al proceso a dormirManejando Interrupciones
Registrando el dispositivoCapabilitiesPasando parametros al driver
variables importantes
/∗ ∗∗ v a r i a b l e donde se almacena e l Major number de l modulo .∗ Se i n i c i a l i z a a 0 para ped i r un numero a l sistema .∗ /
i n t he l l o ma jo r = 0 ;
/∗ ∗∗ Declarac i on de las func iones que usara e l d r i v e r∗ cuando sea accedido .∗ /
struct f i l e o p e r a t i o n s h e l l o f o p s = {. open = hel lo open ,. re lease = he l l o re l ease ,. owner = THIS MODULE} ;
Alejandro Furfaro Linux Devices DriversDesarrollo de un char device
PrerequisitosPrimer Ejemplo
Registro y parametrosScript de Instalacion, No mayor
Poniendo al proceso a dormirManejando Interrupciones
Registrando el dispositivoCapabilitiesPasando parametros al driver
Manejando funciones.../∗ Esta func i on es l a que contes ta r a l os l lamados a l a func i on∗ open ( char ∗ , i n t ) cuyo pr imer parametro corresponda a l nodo∗ en / dev cuyo major number corresponda a l de este d r i v e r ∗ /
i n t he l lo open ( struct inode ∗ inode , struct f i l e ∗ f i l p ){
p r i n t k (KERN INFO ” Hel lo2 : Apertura de Archivo\n ” ) ;return 0;
}
/∗ Esta func i on es l a que contes ta r a l os l lamados a l a func i on∗ open ( char ∗ , i n t ) cuyo pr imer parametro corresponda a l nodo∗ en / dev cuyo major number corresponda a l de este d r i v e r ∗ /
i n t h e l l o r e l e a s e ( struct inode ∗ inode , struct f i l e ∗ f i l p ){
return 0;}
Alejandro Furfaro Linux Devices DriversDesarrollo de un char device
PrerequisitosPrimer Ejemplo
Registro y parametrosScript de Instalacion, No mayor
Poniendo al proceso a dormirManejando Interrupciones
Registrando el dispositivoCapabilitiesPasando parametros al driver
Como se hace...
Se pasan por lınea de comandos al instalar el driverinsmod . / he l l o2 . ko he l l o ma jo r =355
Se reciben en el codigo del modulo en una variable/∗ ∗∗ Declarac i on de parametro de l modulo , \ r e f td3 major .∗ Puede ser seteado por e l user a l hacer e l insmod .∗ ∗ /
module param ( he l lo ma jo r , int , 0 ) ;
module param tiene tres argumentos: nombre, tipo de dato, y lamascara de permisos con la que se creara la entrada en sysfsEl tipo de dato es bool, asociado a una variable que debe ser detipo int, (evaluada como TRUE o FALSE), o invbool queinvierte el valor de la variable, o charp, para manejar strings.luego los tipos clasicos del C: int, long, short, uint,ulong, ushort
Alejandro Furfaro Linux Devices DriversDesarrollo de un char device
PrerequisitosPrimer Ejemplo
Registro y parametrosScript de Instalacion, No mayor
Poniendo al proceso a dormirManejando Interrupciones
Automatizando la instalacionComo obtenemos en No Mayor
Alojando dinamicamente el No Mayor
Al fuente hello3.c y a Makefile, en este tercer ejemplosumamos un shell script para obtener dinamicamente elNumero Mayor, y con el crear automaticamente los nodosnecesarios en el /dev.˜ / DeviceDriverK2 . 6 / d r i ve r3$ cat h e l l o 3 d r i v e r . i n i t
En particular importan las lıneas 59 a 63 del script (activarlasen el editor que esten usando!!)i f $INSMOD $devpath $OPTIONS; then
MAJOR= ‘awk ” \\$2==\ ”$DEVICE\ ” { p r i n t \\$1} ” / proc / devices ‘remove f i l es $FILESc r e a t e f i l e s $FILES
else
Alejandro Furfaro Linux Devices DriversDesarrollo de un char device
PrerequisitosPrimer Ejemplo
Registro y parametrosScript de Instalacion, No mayor
Poniendo al proceso a dormirManejando Interrupciones
Automatizando la instalacionComo obtenemos en No Mayor
Alojando dinamicamente el No Mayor
Al fuente hello3.c y a Makefile, en este tercer ejemplosumamos un shell script para obtener dinamicamente elNumero Mayor, y con el crear automaticamente los nodosnecesarios en el /dev.˜ / DeviceDriverK2 . 6 / d r i ve r3$ cat h e l l o 3 d r i v e r . i n i t
En particular importan las lıneas 59 a 63 del script (activarlasen el editor que esten usando!!)i f $INSMOD $devpath $OPTIONS; then
MAJOR= ‘awk ” \\$2==\ ”$DEVICE\ ” { p r i n t \\$1} ” / proc / devices ‘remove f i l es $FILESc r e a t e f i l e s $FILES
else
Alejandro Furfaro Linux Devices DriversDesarrollo de un char device
PrerequisitosPrimer Ejemplo
Registro y parametrosScript de Instalacion, No mayor
Poniendo al proceso a dormirManejando Interrupciones
Automatizando la instalacionComo obtenemos en No Mayor
Alojando dinamicamente el No Mayor
Al fuente hello3.c y a Makefile, en este tercer ejemplosumamos un shell script para obtener dinamicamente elNumero Mayor, y con el crear automaticamente los nodosnecesarios en el /dev.˜ / DeviceDriverK2 . 6 / d r i ve r3$ cat h e l l o 3 d r i v e r . i n i t
En particular importan las lıneas 59 a 63 del script (activarlasen el editor que esten usando!!)i f $INSMOD $devpath $OPTIONS; then
MAJOR= ‘awk ” \\$2==\ ”$DEVICE\ ” { p r i n t \\$1} ” / proc / devices ‘remove f i l es $FILESc r e a t e f i l e s $FILES
else
Alejandro Furfaro Linux Devices DriversDesarrollo de un char device
PrerequisitosPrimer Ejemplo
Registro y parametrosScript de Instalacion, No mayor
Poniendo al proceso a dormirManejando Interrupciones
Automatizando la instalacionComo obtenemos en No Mayor
awk... mucho mas que un comando
La base es el potente awk (o gawk en Linux, por GNU awk).Veamos un ejemplo desde el shell:˜ / $ awk ” \$2==\ ” sound\ ” { p r i n t \$1} ” / proc / devices14˜ / $ l s −l as / dev / dsp0 crw−rw−−−− 1 roo t audio 14 , 3 nov 8 13:58 / dev / dsp˜ / $
Alejandro Furfaro Linux Devices DriversDesarrollo de un char device
PrerequisitosPrimer Ejemplo
Registro y parametrosScript de Instalacion, No mayor
Poniendo al proceso a dormirManejando Interrupciones
Antes que nada...recursos del kernelMandando a dormir al proceso desde el kernelManejando eficientemente los bloqueos a procesosEscritura del dispositivo
el metodo que pone el proceso a dormir es,tıpicamente, read
Primer paso: agregamos los metodos en File Operations.struct f i l e o p e r a t i o n s h e l l o f o p s = {
. read = he l lo read , / / read ( ) es bloqueante .
. open = hel lo open ,
. re lease = he l l o re l ease ,
. owner = THIS MODULE} ;
Segundo paso: Escribimos la funcion read.s s i z e t he l l o read ( struct f i l e ∗ f i l p , char use r ∗buf ,
s i z e t count , l o f f t ∗ f pos ){i n t r e s u l t ;r e s u l t =copy to user ( buf , kbu f fe r , s t r l e n ( k b u f f e r ) ) ;p r i n t k (KERN INFO ” he l l o4 : d i s p o s i t i v o l e ı do con numero menor
%d\n ” , im inor ( f i l p −>p r i v a t e d a t a ) ) ;return s t r l e n ( k b u f f e r ) ;
}Alejandro Furfaro Linux Devices DriversDesarrollo de un char device
PrerequisitosPrimer Ejemplo
Registro y parametrosScript de Instalacion, No mayor
Poniendo al proceso a dormirManejando Interrupciones
Antes que nada...recursos del kernelMandando a dormir al proceso desde el kernelManejando eficientemente los bloqueos a procesosEscritura del dispositivo
el metodo que pone el proceso a dormir es,tıpicamente, read
Primer paso: agregamos los metodos en File Operations.struct f i l e o p e r a t i o n s h e l l o f o p s = {
. read = he l lo read , / / read ( ) es bloqueante .
. open = hel lo open ,
. re lease = he l l o re l ease ,
. owner = THIS MODULE} ;
Segundo paso: Escribimos la funcion read.s s i z e t he l l o read ( struct f i l e ∗ f i l p , char use r ∗buf ,
s i z e t count , l o f f t ∗ f pos ){i n t r e s u l t ;r e s u l t =copy to user ( buf , kbu f fe r , s t r l e n ( k b u f f e r ) ) ;p r i n t k (KERN INFO ” he l l o4 : d i s p o s i t i v o l e ı do con numero menor
%d\n ” , im inor ( f i l p −>p r i v a t e d a t a ) ) ;return s t r l e n ( k b u f f e r ) ;
}Alejandro Furfaro Linux Devices DriversDesarrollo de un char device
PrerequisitosPrimer Ejemplo
Registro y parametrosScript de Instalacion, No mayor
Poniendo al proceso a dormirManejando Interrupciones
Antes que nada...recursos del kernelMandando a dormir al proceso desde el kernelManejando eficientemente los bloqueos a procesosEscritura del dispositivo
el metodo que pone el proceso a dormir es,tıpicamente, read
Primer paso: agregamos los metodos en File Operations.struct f i l e o p e r a t i o n s h e l l o f o p s = {
. read = he l lo read , / / read ( ) es bloqueante .
. open = hel lo open ,
. re lease = he l l o re l ease ,
. owner = THIS MODULE} ;
Segundo paso: Escribimos la funcion read.s s i z e t he l l o read ( struct f i l e ∗ f i l p , char use r ∗buf ,
s i z e t count , l o f f t ∗ f pos ){i n t r e s u l t ;r e s u l t =copy to user ( buf , kbu f fe r , s t r l e n ( k b u f f e r ) ) ;p r i n t k (KERN INFO ” he l l o4 : d i s p o s i t i v o l e ı do con numero menor
%d\n ” , im inor ( f i l p −>p r i v a t e d a t a ) ) ;return s t r l e n ( k b u f f e r ) ;
}Alejandro Furfaro Linux Devices DriversDesarrollo de un char device
PrerequisitosPrimer Ejemplo
Registro y parametrosScript de Instalacion, No mayor
Poniendo al proceso a dormirManejando Interrupciones
Antes que nada...recursos del kernelMandando a dormir al proceso desde el kernelManejando eficientemente los bloqueos a procesosEscritura del dispositivo
copy to user y copy from user
A copy from user la utilizaremos cuando nos ocupemos delmetodo write
Alejandro Furfaro Linux Devices DriversDesarrollo de un char device
PrerequisitosPrimer Ejemplo
Registro y parametrosScript de Instalacion, No mayor
Poniendo al proceso a dormirManejando Interrupciones
Antes que nada...recursos del kernelMandando a dormir al proceso desde el kernelManejando eficientemente los bloqueos a procesosEscritura del dispositivo
Hace falta retocar el resto
Tercer paso: en el metodo open (), conseguimos la referenciaa filp->private data./∗ ∗∗ puntero a b u f f e r de cada device .∗ ∗ /
char ∗ k b u f f e r ;i n t he l lo open ( struct inode ∗ inode , struct f i l e ∗ f i l p ) {
unsigned i n t minor number = im inor ( inode ) ;p r i n t k (KERN INFO ” he l l o4 : device %d opened\n ” , minor number ) ;/∗ ∗∗ Para que los o t ros metodos puedan obtener e l numero menor ,∗ l o guardo en e l campo p r i v a t e d a t a de l a e s t r u c t u r a f i l e .∗ ∗ /f i l p −>p r i v a t e d a t a = inode ;k b u f f e r = kmal loc ( s t r l e n ( INIT STRING ) , GFP KERNEL ) ;memcpy ( ( char ∗ ) kbu f fe r , INIT STRING , s t r l e n ( INIT STRING ) + 1 ) ;return 0;
}Alejandro Furfaro Linux Devices DriversDesarrollo de un char device
PrerequisitosPrimer Ejemplo
Registro y parametrosScript de Instalacion, No mayor
Poniendo al proceso a dormirManejando Interrupciones
Antes que nada...recursos del kernelMandando a dormir al proceso desde el kernelManejando eficientemente los bloqueos a procesosEscritura del dispositivo
Semaforos del kernel
Primero instanciamos la estructura semaphore que define un semaforodel kernel, e inicializamos el semaforo en el metodo open().
/∗ ∗∗ puntero a b u f f e r de cada device .∗ ∗ /
char ∗ k b u f f e r ;/∗ ∗∗ Semaforos para s i n c r o n i z a r e l acceso a l b u f f e r .∗ ∗ /
struct semaphore sem;i n t he l lo open ( struct inode ∗ inode , struct f i l e ∗ f i l p ) {
unsigned i n t minor number = im inor ( inode ) ;p r i n t k (KERN INFO ” he l l o5 : device %d opened\n ” , minor number ) ;k b u f f e r =NULL ;sema in i t (&sem , 1 ) ; / / l i be rado , para c o n t r o l de acceso a k b u f f e rreturn 0;
}
Alejandro Furfaro Linux Devices DriversDesarrollo de un char device
PrerequisitosPrimer Ejemplo
Registro y parametrosScript de Instalacion, No mayor
Poniendo al proceso a dormirManejando Interrupciones
Antes que nada...recursos del kernelMandando a dormir al proceso desde el kernelManejando eficientemente los bloqueos a procesosEscritura del dispositivo
Tomando el semaforo
Una vez creado lo manejamos desde el metodo read (). Usamos lafamilia de funciones down () del kernel
s s i z e t he l l o read ( struct f i l e ∗ f i l p , char use r ∗buf ,s i z e t count , l o f f t ∗ f pos )
{i f ( ! d o w n i n t e r r u p t i b l e (&sem ) ){
k b u f f e r = kmal loc ( s t r l e n ( INIT STRING )+1 , GFP KERNEL ) ;memcpy ( ( char ∗ ) kbu f fe r , INIT STRING , s t r l e n ( INIT STRING ) + 1 ) ;/∗ copio e l contenido a l b u f f e r de l usuar io ∗ /i f ( copy to user ( buf , kbu f fe r , s t r l e n ( k b u f f e r ) ) ){
up(&sem ) ;p r i n t k (KERN INFO ” he l l o5 : E r ro r de Lectura en copy to user \n ” ) ;return −EFAULT;
}
Alejandro Furfaro Linux Devices DriversDesarrollo de un char device
PrerequisitosPrimer Ejemplo
Registro y parametrosScript de Instalacion, No mayor
Poniendo al proceso a dormirManejando Interrupciones
Antes que nada...recursos del kernelMandando a dormir al proceso desde el kernelManejando eficientemente los bloqueos a procesosEscritura del dispositivo
liberando el semaforo
La funcion de liberacion de un semaforo es: voidup(struct semaphore *sem);
else{
up(&sem ) ;p r i n t k (KERN INFO ” he l l o5 : Lectura ex i tosa , %d bytes \n ” , s t r l e n ( k b u f f e r ) ) ;return s t r l e n ( k b u f f e r ) ;
}}else{
p r i n t k (KERN INFO ” he l l o5 :Lectura con e r r o r toma de semaforo \n ” ) ;
return −EFAULT;}
}
Alejandro Furfaro Linux Devices DriversDesarrollo de un char device
PrerequisitosPrimer Ejemplo
Registro y parametrosScript de Instalacion, No mayor
Poniendo al proceso a dormirManejando Interrupciones
Antes que nada...recursos del kernelMandando a dormir al proceso desde el kernelManejando eficientemente los bloqueos a procesosEscritura del dispositivo
funciones down
En el mundo Linux, la funcion P se llama down (o algunavariedad de ese nombre).‘‘down’’ se refiere al hecho que su operacion consisteen:
decrementar el valor del semaforo,por lo general pone a “dormir” al proceso que invoco almetodo del modulo, hasta que el semaforo se libere,permitir el acceso a un recurso de manera segura
Alejandro Furfaro Linux Devices DriversDesarrollo de un char device
PrerequisitosPrimer Ejemplo
Registro y parametrosScript de Instalacion, No mayor
Poniendo al proceso a dormirManejando Interrupciones
Antes que nada...recursos del kernelMandando a dormir al proceso desde el kernelManejando eficientemente los bloqueos a procesosEscritura del dispositivo
funciones down
Hay tres variantes o versiones de downvoid down(struct semaphore *sem);int down interruptible(struct semaphore*sem);int down trylock(struct semaphore *sem);
down decrementa el valor del semaforo y espera lo queresulte necesario.down interruptible hace lo mismo pero la operaciones interrumpible.down trylock nunca duerme. Si el semaforo noesta disponible al momento de la llamada, retornaimmediatamente un valor no nulo.
Alejandro Furfaro Linux Devices DriversDesarrollo de un char device
PrerequisitosPrimer Ejemplo
Registro y parametrosScript de Instalacion, No mayor
Poniendo al proceso a dormirManejando Interrupciones
Antes que nada...recursos del kernelMandando a dormir al proceso desde el kernelManejando eficientemente los bloqueos a procesosEscritura del dispositivo
Versiones Interrumpibles vs. No Interrumpibles
..
Debemos siempre tratar de utilizar la version interrumpiblede cualquier llamada para dormir un proceso, ya que permiteque desde el espacio de usuario, el proceso que esta dor-mido esperando (por un semaforo en este caso), pueda serinterrumpido por el usuario.
Alejandro Furfaro Linux Devices DriversDesarrollo de un char device
PrerequisitosPrimer Ejemplo
Registro y parametrosScript de Instalacion, No mayor
Poniendo al proceso a dormirManejando Interrupciones
Antes que nada...recursos del kernelMandando a dormir al proceso desde el kernelManejando eficientemente los bloqueos a procesosEscritura del dispositivo
Versiones Interrumpibles vs. No Interrumpibles
Regla generalNo usar operaciones No interrumpibles, a menos que seaabsolutamente necesario. Las operaciones No Interrumpiblesson una excelente forma de crear procesos que no puedan serterminados de ninguna manera posible (aparecen en estado Dpor Dreaded en la salida de ps).El uso de down interruptible requiere algunasprecaucionea adicionales, sin embargo, al ser interrumpida laoperacion, la funcion retorna un valor no nulo, y el procesollamante no mantiene el semaforo.Por lo tanto, el uso correcto de down interruptible requieresiempre chequear el valor retornado, y responder de maneraacorde al proceso invocante.
Alejandro Furfaro Linux Devices DriversDesarrollo de un char device
PrerequisitosPrimer Ejemplo
Registro y parametrosScript de Instalacion, No mayor
Poniendo al proceso a dormirManejando Interrupciones
Antes que nada...recursos del kernelMandando a dormir al proceso desde el kernelManejando eficientemente los bloqueos a procesosEscritura del dispositivo
Durmiendo y despertando al escribir
Antes de mirar este tramo de codigo, conviene abrirhello5.c y mirar la definicion de file operations ;)
s s i z e t h e l l o w r i t e ( struct f i l e ∗ f i l p , const char use r ∗buf ,s i z e t count , l o f f t ∗ f pos ) {
i f ( ! d o w n i n t e r r u p t i b l e (&sem ) ) {k f ree ( k b u f f e r ) ; /∗ destruyo e l b u f f e r ac tua l ∗ // / p ido ( count ) bytes , espec i f i cados por e l usuar io .k b u f f e r = kmal loc ( count , GFP KERNEL ) ;i f ( ! k b u f f e r ) {
/∗ s i hubo un er ro r , devuelvo −ENONMEM∗ /p r i n t k (KERN INFO ” he l l o5 : E s c r i t u r a con e r r o r acceso a memoria \n ” ) ;k b u f f e r = NULL ;up(&sem ) ;return −ENOMEM;}
Alejandro Furfaro Linux Devices DriversDesarrollo de un char device
PrerequisitosPrimer Ejemplo
Registro y parametrosScript de Instalacion, No mayor
Poniendo al proceso a dormirManejando Interrupciones
Antes que nada...recursos del kernelMandando a dormir al proceso desde el kernelManejando eficientemente los bloqueos a procesosEscritura del dispositivo
Durmiendo y despertando al escribir/∗ copio a k b u f f e r e l buf de l usuar io ,∗ s i hay e r r o r devuelvo −EFAULT ∗ /i f ( copy from user ( kbu f fe r , buf , count ) ) {
p r i n t k (KERN INFO ” he l l o5 : E s c r i t u r a con e r r o r en copy from user \n ” ) ;k f ree ( k b u f f e r ) ;up(&sem ) ;return −EFAULT;}
else {p r i n t k (KERN INFO ” he l l o5 : E s c r i t u r a kmal loc para %d bytes \n ” , count ) ;p r i n t k (KERN INFO ” he l l o5 : %s \n ” , k b u f f e r ) ;up(&sem ) ;return count ;}
}else {
p r i n t k (KERN INFO ” he l l o5 : E s c r i t u r a con e r r o r toma de semaforo \n ” ) ;return −EFAULT;}
return 0;} Alejandro Furfaro Linux Devices DriversDesarrollo de un char device
PrerequisitosPrimer Ejemplo
Registro y parametrosScript de Instalacion, No mayor
Poniendo al proceso a dormirManejando Interrupciones
Para usar una IRQ se la pedimos al kernelel handlerbloquenado procesos
¿Donde se pide?
Abrir holla6.c e ir al metodo open ().
i n t he l lo open ( struct inode ∗ inode , struct f i l e ∗ f i l p ) {unsigned i n t minor number = im inor ( inode ) ;p r i n t k (KERN INFO ” he l l o6 : device %d opened\n ” , minor number ) ;k b u f f e r =NULL ;sema in i t (&sem , 0 ) ; / / tomado , para c o n t r o l de acceso a k b u f f e rt i c k c o u n t e r = TICK RELOAD ;p r i n t k ( KERN INFO ” he l l o6 : Opening i r q device\n ” ) ;i f ( r e q u e s t i r q ( IRQ USED, &my handler , IRQF SHARED, ” he l l o6 ” , ” ufa ” ) )
return −EBUSY;p r i n t k ( KERN INFO ” he l l o6 : i r q t i c k c o u n t e r = %d\n ” , t i c k c o u n t e r ) ;p r i n t k ( KERN INFO ” he l l o6 : Salgo de l Opening i r q device\n ” ) ;return 0;
}
Alejandro Furfaro Linux Devices DriversDesarrollo de un char device
PrerequisitosPrimer Ejemplo
Registro y parametrosScript de Instalacion, No mayor
Poniendo al proceso a dormirManejando Interrupciones
Para usar una IRQ se la pedimos al kernelel handlerbloquenado procesos
que hacemos en el hadnler?
Accedemos al hardware, ydespertamos al proceso que ha sido bloqueado cuandosolicito los datos disponibles
i r q r e t u r n t my handler ( i n t i r q , void ∗dev id ) / / , s t r u c t p t regs ∗ regs ){
t i c k c o u n t e r −−;p r i n t k (KERN INFO ” he l l o6 : my handler con t i c k c o u n t e r= %d \n ” , t i c k c o u n t e r ) ;i f ( ! t i c k c o u n t e r ) {
p r i n t k (KERN INFO ” he l l o6 : t i c k c o u n t e r =0 l i b e r o sem \n ” ) ;t i c k c o u n t e r = TICK RELOAD ;up(&sem ) ;w a k e u p i n t e r r u p t i b l e (& td ig wa i tqueue ) ;}
return IRQ HANDLED;}
Alejandro Furfaro Linux Devices DriversDesarrollo de un char device
PrerequisitosPrimer Ejemplo
Registro y parametrosScript de Instalacion, No mayor
Poniendo al proceso a dormirManejando Interrupciones
Para usar una IRQ se la pedimos al kernelel handlerbloquenado procesos
No lo habıamos hecho con semaforos? que mas?
Utilizamos colas de mensaje/∗ ∗∗ Waitqueue que usaremos en e l modo de espera .∗ /
DECLARE WAIT QUEUE HEAD( td ig wa i tqueue ) ;
Cuando el proceso requiere los datos (invoca el metodoread () de nuestro modulo), lo bloqueamos hasta que losdatos esten disponibles, utilizando otras funciones algomas poderosas que los semafoross s i z e t he l l o read ( struct f i l e ∗ f i l p , char use r ∗buf , s i z e t count , l o f f t ∗ f pos ) {
p r i n t k (KERN INFO ” he l l o6 : Lectura ingreso\n ” ) ;i f ( ! d o w n i n t e r r u p t i b l e (&sem ) ){
k b u f f e r = kmal loc ( s t r l e n ( INIT STRING )+1 , GFP KERNEL ) ;memcpy( ( char ∗ ) kbu f fe r , INIT STRING , s t r l e n ( INIT STRING ) + 1 ) ;
Alejandro Furfaro Linux Devices DriversDesarrollo de un char device
PrerequisitosPrimer Ejemplo
Registro y parametrosScript de Instalacion, No mayor
Poniendo al proceso a dormirManejando Interrupciones
Para usar una IRQ se la pedimos al kernelel handlerbloquenado procesos
No lo habıamos hecho con semaforos? que mas?
Utilizamos colas de mensaje/∗ ∗∗ Waitqueue que usaremos en e l modo de espera .∗ /
DECLARE WAIT QUEUE HEAD( td ig wa i tqueue ) ;
Cuando el proceso requiere los datos (invoca el metodoread () de nuestro modulo), lo bloqueamos hasta que losdatos esten disponibles, utilizando otras funciones algomas poderosas que los semafoross s i z e t he l l o read ( struct f i l e ∗ f i l p , char use r ∗buf , s i z e t count , l o f f t ∗ f pos ) {
p r i n t k (KERN INFO ” he l l o6 : Lectura ingreso\n ” ) ;i f ( ! d o w n i n t e r r u p t i b l e (&sem ) ){
k b u f f e r = kmal loc ( s t r l e n ( INIT STRING )+1 , GFP KERNEL ) ;memcpy( ( char ∗ ) kbu f fe r , INIT STRING , s t r l e n ( INIT STRING ) + 1 ) ;
Alejandro Furfaro Linux Devices DriversDesarrollo de un char device
PrerequisitosPrimer Ejemplo
Registro y parametrosScript de Instalacion, No mayor
Poniendo al proceso a dormirManejando Interrupciones
Para usar una IRQ se la pedimos al kernelel handlerbloquenado procesos
No lo habıamos hecho con semaforos? que mas?
Utilizamos colas de mensaje/∗ ∗∗ Waitqueue que usaremos en e l modo de espera .∗ /
DECLARE WAIT QUEUE HEAD( td ig wa i tqueue ) ;
Cuando el proceso requiere los datos (invoca el metodoread () de nuestro modulo), lo bloqueamos hasta que losdatos esten disponibles, utilizando otras funciones algomas poderosas que los semafoross s i z e t he l l o read ( struct f i l e ∗ f i l p , char use r ∗buf , s i z e t count , l o f f t ∗ f pos ) {
p r i n t k (KERN INFO ” he l l o6 : Lectura ingreso\n ” ) ;i f ( ! d o w n i n t e r r u p t i b l e (&sem ) ){
k b u f f e r = kmal loc ( s t r l e n ( INIT STRING )+1 , GFP KERNEL ) ;memcpy( ( char ∗ ) kbu f fe r , INIT STRING , s t r l e n ( INIT STRING ) + 1 ) ;
Alejandro Furfaro Linux Devices DriversDesarrollo de un char device
PrerequisitosPrimer Ejemplo
Registro y parametrosScript de Instalacion, No mayor
Poniendo al proceso a dormirManejando Interrupciones
Para usar una IRQ se la pedimos al kernelel handlerbloquenado procesos
No lo habıamos hecho con semaforos? que mas?i f ( copy to user ( buf , kbu f fe r , s t r l e n ( k b u f f e r ) ) ) /∗ copio e l contenido a l b u f f e r de l usuar io ∗ /{
up(&sem ) ;p r i n t k (KERN INFO ” he l l o6 : Lectura con e r r o r en copy to user \n ” ) ;return −EFAULT;}
else{
/ / up(&sem ) ;p r i n t k (KERN INFO ” he l l o6 : Lectura ex i tosa , %d bytes \n ” , s t r l e n ( k b u f f e r ) ) ;return s t r l e n ( k b u f f e r ) ;}
}else{p r i n t k (KERN INFO ” he l l o6 : Lectura con e r r o r toma de semaforo \n ” ) ;return −EFAULT;}
}
Alejandro Furfaro Linux Devices DriversDesarrollo de un char device
Top Related