电脑技术学习

FreeBSD SNP 2.Server端--自我测试连线

dn001
发信人:;hhuu(不知道爱我的是爱我的人),;信区:;FreeBSD
标 题:;FreeBSD;kld简介
发信站:;BBS;水木清华站

上面的东西大致是daemonnews上的一片文章;by;Andrew;
在google上可以找到.
我觉得将的太罗索,还有一点小错误.改一改,放到这里来.
你要是感兴趣的话,千万去thc看看.
最后在强调一下
原文的作者是
Andrew;Reiter;
http://www.subterrain.net/~awr/KLD-Turorial/

就象Linux下的lkm一样,FreeBSD中有相应的东东.
如果我没有搞错的话,2.x系列中是叫lkm的.现在
还有系统的同志可以在/usr/share/example/lkm
中看到这些前辈的影子.
但是时代变迁,到了3.x系列之后,新的东西出现
了,就是所谓的kld.
这里摘录的是关于FreeBSD的lkm和kld的比较:
1.;LKM;system;used;a;userland;linker;to
push;prerelocated;binary;data;into
the;kernel.
2.;KLD;system;does;the;relocation;itself
in;the;kernel.;LKMs;had;special;data
structures;that;the;lkm;driver;knew;about
and;used;those;to;wire;it;into;the;kernel
3.;LKMs;were;single;purpose;and;were;quite
difficult;to;change;from;LKM;to;actual
kernel;code.
4.;With;KLDs,;thins;were;made;to;be;more
generic.;A;file;could;contain;0;or;more
modules.
5.;Each;module;is;self-contianed;and;self-
initializing;and;registering.
6.;KLDs;and;kernel;code;are;compiled;the
same.
7.;It's;possible;to;take;a;piece;of;the
kernel;and;easily;make;it;a;KLD;without
much;difficulty.
8.;The;dependncies;and;versioning;are;now
at;the;module;level.


我们都知道kld有什么好处了,那么就开始作
一个吧.;标准的例子在/usr/share/example/kld.
btw:;3.x系列的还有lkm的目录,有人愿意看吗?
kld目录中有两个子目录,对应了两种主要的方法.
写设备驱动(cdev)和增加系统调用(syscall).
我们还是从一般的情况开始吧.
所有的kld都会有一个类似的函数:
static;int
load_handler;(module_t;mod,;int;what,;void;*arg)
{
int;err=0;
switch(what);{
case;MOD_LOAD:
........
break;
case;MOD_UNLOAD:
.......
break;
default:
err=EINVAL;
break;
}
return;(err);
}
大家都觉得很面善吧.看上去和init_module没有太大
的区别.上面的函数格式格式可以在/usr/include/sys/module.h
中找到.
typedef;int;(*modeventhand_t)(module_t;mod,;int;what,;void;*arg);
这个module_t;mod是指向module结构的指针.从它可以牵出所有的
被载入的模块.
int;what是modeventtype_t的值之一.
MOD_LOAD:
MOD_UNLOAD:
MOD_SHUTDOWN:;上面两个就不用说了.这个shutdown的意思
似乎是指机器shutdown时kld的行为.

所有的kld都需要注册.所以就有了一个通用的宏:
DECLARE_MODULE(;name,;data,;sub,;order)
定义在/usr/include/sys/module.h
name:;就是kld的名字
data:;是个moduledata类型的东东.
sub:;;在/usr/include/sys/kernel.h里定义的
sysinit_sub_id的值.
order:在/usr/include/sys/kernel.h里面的
sysinit_elem_order
看看就明白了,没有什么大不了的.
(Declare_module还调用的sysinit......其实也不过是....
...........;#%@^#&$^%*&$^)
考虑到我们写module不过是为了设备驱动或者
增加系统调用罢了.所以就有了两个常用的宏.
DEV_MODULE和SYSCALL_MODULE
分别在/usr/include/sys/conf.h和sys/sysent.h中
也就是对DECLARE_MODULE的简单包装.

回想我们在linux下编译一个模块时无非是
gcc;-DMODULE;-D__KERNEL__;-DLINUX;-O3;-c;....
可是在FreeBSD下就不是这么好办了.看看
前面说的那两个例子编译时出来的那么一
大堆,我就先吓坏了.
感谢上帝,不是没一个人都要搞得那么清楚才能
编译kld的.我们的Makefle关键在于.include
只要包含了bsd.kmod.mk,我们自己要作的事就是
SRCS=;源文件名
KMOD=;目标模块的名字
如果你是爱刨根问底的,请看/usr/share/mk

还是关于syscall的问题.
在sys/sysent.h中有定义
struct;sysent;{
int;sy_narg;
sy_call_t;*sy_call;
};
这分明是linux下面那个
sys_call_table么.
有区别的就是那个offset.
可以用offset=NO_SYSCALL来让系统在载入的时候
自动选择syscall;number.
回顾一下,我们的任务是要有一个
load_xxx函数来处理load和unload的情况
要有我们自己的调用.
最后SYSCALL_MODULE来注册.

如果是设备模块的话.
我们需要一张表
/usr/include/sys/conf.h中定义的
struct;cdevsw;{.....}
然后的过程和上面几乎一模一.....
就这样吧.强力推荐
1;http://thc.pimmel.com/files/thc/bsdkern.html
2;/usr/share/example/kld/

标签: