Livre de chevet du développeur FreeBSD | ||
---|---|---|
Précédent | Chapitre 16. Ecrire des pilotes de périphériques pour FreeBSD | Suivant |
Un pilote de périphérique caractère est un pilote qui tranfère les données directement au processus utilisateur ou vers celui-ci. Il s'agit du plus commun des types de pilote de périphérique et il y en a plein d'exemples simples dans l'arbre des sources.
Cet exemple simple de pseudo-périphérique enregistre toutes les valeurs que vous lui avez écrites et peut vous les renvoyer quand vous les lui demandez.
/* * un simple pseudo-périphérique `echo' KLD * * Murray Stokely */ #define MIN(a,b) (((a) < (b)) ? (a) : (b)) #include <sys/types.h> #include <sys/module.h> #include <sys/systm.h> /* uprintf */ #include <sys/errno.h> #include <sys/param.h> /* defines utilises dans kernel.h */ #include <sys/kernel.h> /* types utilises dans me module d'initialisation */ #include <sys/conf.h> /* cdevsw struct */ #include <sys/uio.h> /* uio struct */ #include <sys/malloc.h> #define BUFFERSIZE 256 /* Prototypes des fonctions */ d_open_t echo_open; d_close_t echo_close; d_read_t echo_read; d_write_t echo_write; /* Points d'entrée du périphérique Caractère */ static struct cdevsw echo_cdevsw = { echo_open, echo_close, echo_read, echo_write, noioctl, nopoll, nommap, nostrategy, "echo", 33, /* reserve pour lkms - /usr/src/sys/conf/majors */ nodump, nopsize, D_TTY, -1 }; typedef struct s_echo { char msg[BUFFERSIZE]; int len; } t_echo; /* variables */ static dev_t sdev; static int len; static int count; static t_echo *echomsg; MALLOC_DECLARE(M_ECHOBUF); MALLOC_DEFINE(M_ECHOBUF, "echobuffer", "cache pour le module echo"); /* * Cette fonction est appele par les appels systeme kld[un]load(2) pour * determiner quelles actions doivent etre faites quand le * module est charge ou decharge */ static int echo_loader(struct module *m, int what, void *arg) { int err = 0; switch (what) { case MOD_LOAD: /* kldload */ sdev = make_dev(&echo_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, "echo"); /* aloocation de mémoire noyau pour l'utilisation de ce module */ /* malloc(256,M_ECHOBUF,M_WAITOK); */ MALLOC(echomsg, t_echo *, sizeof(t_echo), M_ECHOBUF, M_WAITOK); printf("Peripherique Echo charge.\n"); break; case MOD_UNLOAD: destroy_dev(sdev); FREE(echomsg,M_ECHOBUF); printf("Peripherique Echo decharge.\n"); break; default: err = EINVAL; break; } return(err); } int echo_open(dev_t dev, int oflags, int devtype, struct proc *p) { int err = 0; uprintf("Peripherique \"echo\" ouvert avec succes.\n"); return(err); } int echo_close(dev_t dev, int fflag, int devtype, struct proc *p) { uprintf("Fermeture du peripherique \"echo.\"\n"); return(0); } /* * La fonction read prend juste comme parametre * le cache qui a ete sauve par l'appel à echo_write() * et le retourne a l'utilisateur pour acces. * uio(9) */ int echo_read(dev_t dev, struct uio *uio, int ioflag) { int err = 0; int amt; /* De quelle taille est cette operation read ? Aussi grande que l'utilisateur le veut, ou aussi grande que les donnees restantes */ amt = MIN(uio->uio_resid, (echomsg->len - uio->uio_offset > 0) ? echomsg->len - uio->uio_offset : 0); if ((err = uiomove(echomsg->msg + uio->uio_offset,amt,uio)) != 0) { uprintf("uiomove echoue!\n"); } return err; } /* * echo_write prend un caractere en entree et le sauve * dans le cache pour une utilisation ulterieure. */ int echo_write(dev_t dev, struct uio *uio, int ioflag) { int err = 0; /* Copie la chaine d'entree de la memoire de l'utilisateur a la memoire du noyau*/ err = copyin(uio->uio_iov->iov_base, echomsg->msg, MIN(uio->uio_iov->iov_len,BUFFERSIZE)); /* Maintenant nous avons besoin de terminer la chaine par NULL */ *(echomsg->msg + MIN(uio->uio_iov->iov_len,BUFFERSIZE)) = 0; /* Enregistre la taille */ echomsg->len = MIN(uio->uio_iov->iov_len,BUFFERSIZE); if (err != 0) { uprintf("Ecriture echouee: mauvaise adresse!\n"); } count++; return(err); } DEV_MODULE(echo,echo_loader,NULL);
Pour installer ce pilote, vous devrez d'abord créer un fichier spécial dans votre système de fichiers avec une commande comme :
# mknod /dev/echo c 33 0
Avec ce pilote chargé, vous devriez maintenant êtr capable de taper quelque chose comme :
# echo -n "Test Donnees" > /dev/echo # cat /dev/echo Test Donnees
Périphériques réels dans le chapître suivant.
Informations additionnelles
Dynamic Kernel Linker (KLD) Facility Programming Tutorial - Daemonnews October 2000
How to Write Kernel Drivers with NEWBUS - Daemonnews July 2000
Précédent | Sommaire | Suivant |
Accéder au pilote d'un périphérique | Niveau supérieur | Pilotes Réseau |
Ce document, ainsi que d'autres peut être téléchargé sur ftp.FreeBSD.org/pub/FreeBSD/doc/.
Pour toutes questions à propos de FreeBSD, lisez la documentation avant de contacter <[email protected]>.
Pour les questions sur cette documentation, contactez <[email protected]>.