1 ¼ò½é
¡¡¡¡±¾Õ¼òÒª½éÉÜÁËÈçºÎΪFreeBSD±àдÉ豸Çý¶¯³ÌÐò¡£ÊõÓïÉ豸ÔÚÕâ¶ùµÄÉÏÏÂÎÄÖжàÓÃÓÚÖ¸´úϵͳÖÐÓ²¼þÏà¹ØµÄ¶«Î÷£¬Èç´ÅÅÌ£¬´òÓ¡»ú£¬Í¼ÐÎÏÔʽÆ÷¼°Æä¼üÅÌ¡£É豸Çý¶¯³ÌÐòÊDzÙ×÷ϵͳÖÐÓÃÓÚ¿ØÖÆÌض¨É豸µÄÈí¼þ×é¼þ¡£Ò²ÓÐËùνµÄαÉ豸£¬¼´É豸Çý¶¯³ÌÐòÓÃÈí¼þÄ£ÄâÉ豸µÄÐÐΪ£¬¶øûÓÐÌض¨µÄµ×²ãÓ²¼þ¡£É豸Çý¶¯³ÌÐò¿ÉÒÔ±»¾²Ì¬µØ±àÒë½øϵͳ£¬»òÕßͨ¹ý¶¯Ì¬ÄÚºËÁ´½Ó¹¤¾ß¡®kld¡¯ÔÚÐèҪʱ¼ÓÔØ¡£
¡¡¡¡ÀàUNIX®²Ù×÷ϵͳÖеĴó¶àÊýÉ豸¶¼ÊÇͨ¹ýÉ豸½ÚµãÀ´·ÃÎʵģ¬ÓÐʱҲ±»³ÆΪÌØÊâÎļþ¡£ÕâЩÎļþÔÚÎļþϵͳµÄ²ã´Î½á¹¹ÖÐͨ³£Î»ÓÚ /devĿ¼Ï¡£ÔÚFreeBSD 5.0-RELEASEÒÔÇ°µÄ ·¢ÐаæÖÐ, ¶Ô devfs(5)µÄÖ§³Ö»¹Ã»Óб»¼¯³Éµ½FreeBSDÖУ¬Ã¿¸öÉ豸½Úµã±ØÐëÒª¾²Ì¬´´½¨£¬²¢ÇÒ¶ÀÁ¢ÓÚÏà¹ØÉ豸Çý¶¯³ÌÐòµÄ´æÔÚ¡£ÏµÍ³Öдó ¶àÊýÉ豸½ÚµãÊÇͨ¹ýÔËÐÐMAKEDEV´´½¨µÄ¡£
¡¡¡¡É豸Çý¶¯³ÌÐò¿ÉÒÔ´ÖÂԵطÖΪÁ½À࣬×Ö·ûºÍÍøÂçÉ豸Çý¶¯³ÌÐò¡£
JustForLOVE ÓÚ 2007-09-06 10:58:13·¢±í:
6 ÍøÂçÉ豸Çý¶¯³ÌÐò
¡¡¡¡·ÃÎÊÍøÂçÉ豸µÄÇý¶¯³ÌÐò²»ÐèҪʹÓÃÉ豸½Úµã¡£Ñ¡ÔñÄĸöÇý¶¯³ÌÐòÊÇ»ùÓÚÄÚºËÄÚ²¿µÄÆäËû¾ö¶¨¶ø²»Êǵ÷ÓÃopen()£¬¶ÔÍøÂçÉ豸µÄʹÓÃͨ³£ÓÉϵͳµ÷ÓÃsocket(2)ÒýÈë¡£
¡¡¡¡¸ü¶àϸ½Ú£¬ Çë²Î¼û ifnet(9) Áª»úÊֲᡢ »Ø»·É豸µÄÔ´´úÂ룬 ÒÔ¼° Bill Paul ׫дµÄÍøÂçÇý¶¯³ÌÐò¡£
JustForLOVE ÓÚ 2007-09-06 10:49:14·¢±í:
5 ¿éÉ豸(ÏûÍöÖÐ)
¡¡¡¡ÆäËûUNIX®ÏµÍ³Ö§³ÖÁíÒ»ÀàÐ͵ĴÅÅÌÉ豸£¬³ÆΪ¿éÉ豸¡£¿éÉ豸ÊÇÄÚºËΪËüÃÇÌṩ»º³åµÄ´ÅÅÌÉ豸¡£ÕâÖÖ»º³åʹµÃ¿éÉ豸¼¸ºõûÓÐÓ㬻òÕß˵·Ç³£²»¿É¿¿¡£»º³å»áÖØа²ÅÅд²Ù×÷µÄ´ÎÐò£¬Ê¹µÃÓ¦ÓóÌÐòɥʧÁËÔÚÈκÎʱ¿Ì¼°Ê±ÖªµÀ׼ȷµÄ´ÅÅÌÄÚÈݵÄÄÜÁ¦¡£Õâµ¼Ö¶ԴÅÅÌÊý¾Ý½á¹¹£¨Îļþϵͳ£¬Êý¾Ý¿âµÈ£©µÄ¿ÉÔ¤²âµÄºÍ¿É¿¿µÄ±ÀÀ£»Ö¸´³ÉΪ²»¿ÉÄÜ¡£ÓÉÓÚд²Ù×÷±»ÑÓ³Ù£¬ÄÚºËÎÞ·¨ÏòÓ¦ÓóÌÐò±¨¸æÄĸöÌض¨µÄд²Ù×÷Óöµ½ÁËд´íÎó£¬ÕâÓÖ½øÒ»²½Ôö¼ÓÁËÒ»ÖÂÐÔÎÊÌâ¡£ÓÉÓÚÕâ¸öÔÒò£¬ÕæÕýµÄÓ¦ÓóÌÐò´Ó²»ÒÀÀµÓÚ¿éÉ豸£¬ÊÂʵÉÏ£¬¼¸ºõËùÓзÃÎÊ´ÅÅ̵ÄÓ¦ÓóÌÐò¶¼¾¡Á¦Ö¸¶¨×ÜÊÇʹÓÃ×Ö·û£¨»ò¡°raw¡±£©É豸¡£ÓÉÓÚʵÏÖ½«Ã¿¸ö´ÅÅÌ£¨·ÖÇø£©Í¬¾ßÓв»Í¬ÓïÒåµÄÁ½¸öÉ豸»ìΪһ̸£¬´Ó¶øÖÂʹÏà¹ØÄں˴úÂ뼫´óµØ¸´ÔÓ»¯£¬×÷ΪÍƽø´ÅÅÌI/O»ù´¡½á¹¹ÏÖ´ú»¯µÄÒ»²¿·Ö£¬FreeBSD Å×ÆúÁ˶Դø»º³åµÄ´ÅÅÌÉ豸µÄÖ§³Ö¡£
JustForLOVE ÓÚ 2007-09-06 10:48:23·¢±í:
4 ×Ö·ûÉ豸
/* uprintf */
/* kernel.hÖÐÓõ½µÄ¶¨Òå */
/* Ä£¿é³õʼ»¯ÖÐʹÓõÄÀàÐÍ */
/* cdevsw½á¹¹ */
/* uio½á¹¹ */
/* uprintf */
/* kernel.hÖÐÓõ½µÄ¶¨Òå */
/* Ä£¿é³õʼ»¯ÖÐʹÓõÄÀàÐÍ */
/* cdevsw½á¹¹ */
/* uio½á¹¹ */
¡¡¡¡×Ö·ûÉ豸Çý¶¯³ÌÐòÖ±½Ó´ÓÓû§½ø³Ì´«ÊäÊý¾Ý£¬»ò´«ÊäÊý¾Ýµ½Óû§½ø³Ì¡£ÕâÊÇ×îÆÕͨµÄÒ»ÀàÉ豸Çý¶¯³ÌÐò£¬Ô´ÂëÊ÷ÖÐÓдóÁ¿µÄ¼òµ¥Àý×Ó¡£
¡¡¡¡Õâ¸ö¼òµ¥µÄαÉ豸Àý×Ó»á¼ÇסÄãд¸øËüµÄÈκÎÖµ£¬²¢ÇÒµ±Äã¶ÁÈ¡ËüµÄʱºò»á½«ÕâЩֵ·µ»Ø¸øÄã¡£ÏÂÃæÏÔʾÁËÁ½¸ö°æ±¾£¬Ò»¸öÊÊÓÃÓÚFreeBSD 4.X£¬Ò»¸öÊÊÓÃÓÚFreeBSD 5.X¡£
Àý 9-1. ÊÊÓÃÓÚFreeBSD 4.XµÄ»ØÏÔαÉ豸Çý¶¯³ÌÐòʵÀý
/*
* ¼òµ¥¡®echo¡¯Î±É豸KLD
*
* Murray Stokely
*/
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define BUFFERSIZE 256
/* º¯ÊýÔÐÍ */
d_open_t echo_open;
d_close_t echo_close;
d_read_t echo_read;
d_write_t echo_write;
/* ×Ö·ûÉ豸Èë¿Úµã */
static struct cdevsw echo_cdevsw = {
echo_open,
echo_close,
echo_read,
echo_write,
noioctl,
nopoll,
nommap,
nostrategy,
"echo",
33, /* Ϊlkms±£Áô - /usr/src/sys/conf/majors */
nodump,
nopsize,
D_TTY,
-1
};
typedef struct s_echo {
char msg[BUFFERSIZE];
int len;
} t_echo;
/* ±äÁ¿ */
static dev_t sdev;
static int count;
static t_echo *echomsg;
MALLOC_DECLARE(M_ECHOBUF);
MALLOC_DEFINE(M_ECHOBUF, "echobuffer", "buffer for echo module");
/*
* Õâ¸öº¯Êý±»kld[un]load(2)ϵͳµ÷ÓÃÀ´µ÷Óã¬
* ÒÔ¾ö¶¨¼ÓÔغÍжÔØÄ£¿éʱÐèÒª²ÉÈ¡µÄ¶¯×÷¡£
*/
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");
/* kmalloc·ÖÅ乩Çý¶¯³ÌÐòʹÓõÄÄÚ´æ */
MALLOC(echomsg, t_echo *, sizeof(t_echo), M_ECHOBUF, M_WAITOK);
printf("Echo device loaded.\n");
break;
case MOD_UNLOAD:
destroy_dev(sdev);
FREE(echomsg,M_ECHOBUF);
printf("Echo device unloaded.\n");
break;
default:
err = EOPNOTSUPP;
break;
}
return(err);
}
int
echo_open(dev_t dev, int oflags, int devtype, struct proc *p)
{
int err = 0;
uprintf("Opened device \"echo\" successfully.\n");
return(err);
}
int
echo_close(dev_t dev, int fflag, int devtype, struct proc *p)
{
uprintf("Closing device \"echo.\"\n");
return(0);
}
/*
* readº¯Êý½ÓÊÜÓÉecho_write()´æ´¢µÄbuf£¬²¢½«Æä·µ»Øµ½Óû§¿Õ¼ä£¬
* ÒÔ¹©ÆäËûº¯Êý·ÃÎÊ¡£
* uio(9)
*/
int
echo_read(dev_t dev, struct uio *uio, int ioflag)
{
int err = 0;
int amt;
/*
* Õâ¸ö¶Á²Ù×÷Óжà´ó£¿
* ÓëÓû§ÇëÇóµÄ´óСһÑù£¬»òÕßµÈÓÚÊ£ÓàÊý¾ÝµÄ´óС¡£
*/
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 failed!\n");
}
return(err);
}
/*
* echo_write½ÓÊÜÒ»¸ö×Ö·û´®²¢½«Ëü±£´æµ½»º³åÇø£¬ÓÃÓÚÒÔºóµÄ·ÃÎÊ¡£
*/
int
echo_write(dev_t dev, struct uio *uio, int ioflag)
{
int err = 0;
/* ½«×Ö·û´®´ÓÓû§¿Õ¼äµÄÄڴ渴ÖƵ½Äں˿ռä */
err = copyin(uio->uio_iov->iov_base, echomsg->msg,
MIN(uio->uio_iov->iov_len, BUFFERSIZE - 1));
/* ÏÖÔÚÐèÒªÒÔnull½áÊø×Ö·û´®£¬²¢¼Ç¼³¤¶È */
*(echomsg->msg + MIN(uio->uio_iov->iov_len, BUFFERSIZE - 1)) = 0;
echomsg->len = MIN(uio->uio_iov->iov_len, BUFFERSIZE);
if (err != 0) {
uprintf("Write failed: bad address!\n");
}
count++;
return(err);
}
DEV_MODULE(echo,echo_loader,NULL);
Àý 9-2. ÊÊÓÃÓÚFreeBSD 5.X»ØÏÔαÉ豸Çý¶¯³ÌÐòʵÀý
/*
* ¼òµ¥¡®echo¡¯Î±É豸 KLD
*
* Murray Stokely
*
* ´Ë´úÂëÓÉSøren (Xride) Straarupת»»µ½5.X
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define BUFFERSIZE 256
/* º¯ÊýÔÐÍ */
static d_open_t echo_open;
static d_close_t echo_close;
static d_read_t echo_read;
static d_write_t echo_write;
/* ×Ö·ûÉ豸Èë¿Úµã */
static struct cdevsw echo_cdevsw = {
.d_version = D_VERSION,
.d_open = echo_open,
.d_close = echo_close,
.d_read = echo_read,
.d_write = echo_write,
.d_name = "echo",
};
typedef struct s_echo {
char msg[BUFFERSIZE];
int len;
} t_echo;
/* ±äÁ¿ */
static struct cdev *echo_dev;
static int count;
static t_echo *echomsg;
MALLOC_DECLARE(M_ECHOBUF);
MALLOC_DEFINE(M_ECHOBUF, "echobuffer", "buffer for echo module");
/*
* Õâ¸öº¯Êý±»kld[un]load(2)ϵͳµ÷ÓÃÀ´µ÷ÓÃ,
* ÒÔ¾ö¶¨¼ÓÔغÍжÔØÄ£¿éʱÐèÒª²ÉÈ¡µÄ¶¯×÷.
*/
static int
echo_loader(struct module *m, int what, void *arg)
{
int err = 0;
switch (what) {
case MOD_LOAD: /* kldload */
echo_dev = make_dev(&echo_cdevsw,
0,
UID_ROOT,
GID_WHEEL,
0600,
"echo");
/* kmalloc·ÖÅ乩Çý¶¯³ÌÐòʹÓõÄÄÚ´æ */
echomsg = malloc(sizeof(t_echo), M_ECHOBUF, M_WAITOK);
printf("Echo device loaded.\n");
break;
case MOD_UNLOAD:
destroy_dev(echo_dev);
free(echomsg, M_ECHOBUF);
printf("Echo device unloaded.\n");
break;
default:
err = EOPNOTSUPP;
break;
}
return(err);
}
static int
echo_open(struct cdev *dev, int oflags, int devtype, struct thread *p)
{
int err = 0;
uprintf("Opened device \"echo\" successfully.\n");
return(err);
}
static int
echo_close(struct cdev *dev, int fflag, int devtype, struct thread *p)
{
uprintf("Closing device \"echo.\"\n");
return(0);
}
/*
* readº¯Êý½ÓÊÜÓÉecho_write()´æ´¢µÄbuf£¬²¢½«Æä·µ»Øµ½Óû§¿Õ¼ä£¬
* ÒÔ¹©ÆäËûº¯Êý·ÃÎÊ¡£
* uio(9)
*/
static int
echo_read(struct cdev *dev, struct uio *uio, int ioflag)
{
int err = 0;
int amt;
/*
* Õâ¸ö¶Á²Ù×÷Óжà´ó£¿
* µÈÓÚÓû§ÇëÇóµÄ´óС£¬»òÕßµÈÓÚÊ£ÓàÊý¾ÝµÄ´óС¡£
*/
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 failed!\n");
}
return(err);
}
/*
* echo_write½ÓÊÜÒ»¸ö×Ö·û´®²¢½«Ëü±£´æµ½»º³åÇø, ÓÃÓÚÒÔºóµÄ·ÃÎÊ.
*/
static int
echo_write(struct cdev *dev, struct uio *uio, int ioflag)
{
int err = 0;
/* ½«×Ö·û´®´ÓÓû§¿Õ¼äµÄÄڴ渴ÖƵ½Äں˿ռä */
err = copyin(uio->uio_iov->iov_base, echomsg->msg,
MIN(uio->uio_iov->iov_len, BUFFERSIZE - 1));
/* ÏÖÔÚÐèÒªÒÔnull½áÊø×Ö·û´®£¬²¢¼Ç¼³¤¶È */
*(echomsg->msg + MIN(uio->uio_iov->iov_len, BUFFERSIZE - 1)) = 0;
echomsg->len = MIN(uio->uio_iov->iov_len, BUFFERSIZE);
if (err != 0) {
uprintf("Write failed: bad address!\n");
}
count++;
return(err);
}
DEV_MODULE(echo,echo_loader,NULL);
¡¡¡¡ÔÚFreeBSD 4.XÉÏ°²×°´ËÇý¶¯³ÌÐò£¬Ä㽫Ê×ÏÈÐèÒªÓÃÈçÏÂÃüÁîÔÚÄãµÄÎļþϵͳÉÏ´´½¨Ò»¸ö½Úµã£º
# mknod /dev/echo c 33 0
¡¡¡¡Çý¶¯³ÌÐò±»¼ÓÔغó£¬ÄãÓ¦¸ÃÄܹ»¼üÈëһЩ¶«Î÷£¬È磺
# echo -n "Test Data" > /dev/echo
# cat /dev/echo
Test Data
¡¡¡¡ÕæÕýµÄÓ²¼þÉ豸ÔÚÏÂÒ»ÕÂÃèÊö¡£
¡¡¡¡²¹³ä×ÊÔ´
Dynamic Kernel Linker (KLD) Facility Programming Tutorial - Daemonnews October 2000
How to Write Kernel Drivers with NEWBUS - Daemonnews July 2000
JustForLOVE ÓÚ 2007-09-06 10:47:42·¢±í:
3 ·ÃÎÊÉ豸Çý¶¯³ÌÐò
¡¡¡¡UNIX® ÌṩÁËÒ»Ì×¹«¹²µÄϵͳµ÷Óù©Óû§µÄÓ¦ÓóÌÐòʹÓᣵ±Óû§·ÃÎÊÉ豸½Úµãʱ£¬Äں˵ÄÉϲ㽫ÕâЩµ÷Ó÷ַ¢µ½ÏàÓ¦µÄÉ豸Çý¶¯³ÌÐò¡£½Å±¾ /dev/MAKEDEVΪÄãµÄϵͳÉú³ÉÁË´ó¶àÊýµÄÉ豸½Úµã£¬µ«Èç¹ûÄãÕýÔÚ¿ª·¢Äã×Ô¼ºµÄÇý¶¯³ÌÐò£¬¿ÉÄÜÐèÒªÓà mknod´´½¨Äã×Ô¼ºµÄÉ豸½Úµã¡£
3.1 ´´½¨¾²Ì¬É豸½Úµã
¡¡¡¡mknodÃüÁîÐèÒªËĸö²ÎÊýÀ´´´½¨É豸½Úµã¡£Äã±ØÐëÖ¸¶¨É豸½ÚµãµÄÃû×Ö£¬É豸µÄÀàÐÍ£¬É豸µÄÖ÷ºÅÂëºÍÉ豸µÄ´ÓºÅÂë¡£
3.2 ¶¯Ì¬É豸½Úµã
¡¡¡¡É豸Îļþϵͳ£¬»òÕß˵devfs£¬ÔÚÈ«¾ÖÎļþϵͳÃû×Ö¿Õ¼äÖÐÌṩ¶ÔÄÚºËÉ豸Ãû×Ö¿Õ¼äµÄ·ÃÎÊ¡£ÕâÏû³ýÁËÓÉÓÚÓÐÉ豸Çý¶¯³ÌÐò¶øûÓо²Ì¬É豸½Úµã£¬»òÕßÓÐÉ豸½Úµã¶øûÓа²×°É豸Çý¶¯³ÌÐò¶ø´øÀ´µÄDZÔÚÎÊÌâ¡£ DevfsÈÔÔÚ½øÕ¹ÖУ¬µ«ÒѾÄܹ»¹¤×÷µÃÏ൱ºÃÁË¡£
JustForLOVE ÓÚ 2007-09-06 10:46:43·¢±í:
2 ¶¯Ì¬ÄÚºËÁ´½Ó¹¤¾ß©¤©¤KLD
/* uprintf */
/* kernel.hÖÐÓõ½µÄ¶¨Òå */
/* Ä£¿é³õʼ»¯ÖÐʹÓõÄÀàÐÍ */
¡¡¡¡kld½Ó¿ÚÔÊÐíϵͳ¹ÜÀíÔ±´ÓÔËÐеÄϵͳÖж¯Ì¬µØÌí¼ÓºÍɾ³ý¹¦ÄÜ¡£ÕâÔÊÐíÉ豸Çý¶¯³ÌÐòµÄ±àдÕß½«ËûÃǵÄиĶ¯¼ÓÔص½ÔËÐеÄÄÚºËÖУ¬¶ø²»ÓÃΪÁ˲âÊÔиĶ¯¶øƵ·±µØÖØÆô¡£
¡¡¡¡kld½Ó¿Úͨ¹ýÏÂÃæµÄÌØȨÃüÁîʹÓãº
kldload - ¼ÓÔØÐÂÄÚºËÄ£¿é
kldunload - жÔØÄÚºËÄ£¿é
kldstat - Áоٵ±Ç°¼ÓÔصÄÄ£¿é
¡¡¡¡ÄÚºËÄ£¿éµÄ³ÌÐò¿ò¼Ü
/*
* KLD³ÌÐò¿ò¼Ü
* ÊÜAndrew ReiterÔÚDaemonnewsÉϵÄÎÄÕÂËùÆô·¢
*/
#include
#include
#include
#include
#include
#include
/*
* ¼ÓÔØ´¦Àíº¯Êý£¬¸ºÔð´¦ÀíKLDµÄ¼ÓÔغÍжÔØ¡£
*/
static int
skel_loader(struct module *m, int what, void *arg)
{
int err = 0;
switch (what) {
case MOD_LOAD: /* kldload */
uprintf("Skeleton KLD loaded.\n");
break;
case MOD_UNLOAD:
uprintf("Skeleton KLD unloaded.\n");
break;
default:
err = EOPNOTSUPP;
break;
}
return(err);
}
/* ÏòÄÚºËÆäÓಿ·ÖÉùÃ÷´ËÄ£¿é */
static moduledata_t skel_mod = {
"skel",
skel_loader,
NULL
};
DECLARE_MODULE(skeleton, skel_mod, SI_SUB_KLD, SI_ORDER_ANY);
9.2.1 Makefile
¡¡¡¡FreeBSDÌṩÁËÒ»¸ömakefile°üº¬Îļþ£¬ÀûÓÃËüÄã¿ÉÒÔ¿ìËٵرàÒë Ä㸽¼Óµ½Äں˵Ķ«Î÷¡£
SRCS=skeleton.c
KMOD=skeleton
.include
¡¡¡¡¼òµ¥µØÓÃÕâ¸ömakefileÔËÐÐmake¾ÍÄܹ»´´½¨Îļþ skeleton.ko£¬¼üÈëÈçÏÂÃüÁî¿ÉÒÔ°ÑËü¼ÓÔص½Äںˣº
# kldload -v ./skeleton.ko