發(fā)信人: hhuu(不知道愛我的是愛我的人), 信區(qū): FreeBSD
標(biāo) 題: FreeBSD kld簡介
發(fā)信站: BBS 水木清華站
上面的東西大致是daemonnews上的一片文章 by Andrew
在google上可以找到.
我覺得將的太羅索,還有一點(diǎn)小錯(cuò)誤.改一改,放到這里來.
你要是感興趣的話,千萬去thc看看.
最后在強(qiáng)調(diào)一下
原文的作者是
Andrew Reiter
http://www.subterrain.net/~awr/KLD-Turorial/
就象linux下的lkm一樣,FreeBSD中有相應(yīng)的東東.
如果我沒有搞錯(cuò)的話,2.x系列中是叫l(wèi)km的.現(xiàn)在
還有系統(tǒng)的同志可以在/usr/share/example/lkm
中看到這些前輩的影子.
但是時(shí)代變遷,到了3.x系列之后,新的東西出現(xiàn)
了,就是所謂的kld.
這里摘錄的是關(guān)于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有什么好處了,那么就開始作
一個(gè)吧. 標(biāo)準(zhǔn)的例子在/usr/share/example/kld.
btw: 3.x系列的還有l(wèi)km的目錄,有人愿意看嗎?
kld目錄中有兩個(gè)子目錄,對應(yīng)了兩種主要的方法.
寫設(shè)備驅(qū)動(dòng)(cdev)和增加系統(tǒng)調(diào)用(syscall).
我們還是從一般的情況開始吧.
所有的kld都會(huì)有一個(gè)類似的函數(shù):
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沒有太大
的區(qū)別.上面的函數(shù)格式格式可以在/usr/include/sys/module.h
中找到.
typedef int (*modeventhand_t)(module_t mod, int what, void *arg);
這個(gè)module_t mod是指向module結(jié)構(gòu)的指針.從它可以牽出所有的
被載入的模塊.
int what是modeventtype_t的值之一.
MOD_LOAD:
MOD_UNLOAD:
MOD_SHUTDOWN: 上面兩個(gè)就不用說了.這個(gè)shutdown的意思
似乎是指機(jī)器shutdown時(shí)kld的行為.
所有的kld都需要注冊.所以就有了一個(gè)通用的宏:
DECLARE_MODULE( name, data, sub, order)
定義在/usr/include/sys/module.h
name: 就是kld的名字
data: 是個(gè)moduledata類型的東東.
sub: 在/usr/include/sys/kernel.h里定義的
sysinit_sub_id的值.
order:在/usr/include/sys/kernel.h里面的
sysinit_elem_order
看看就明白了,沒有什么大不了的.
(Declare_module還調(diào)用的sysinit......其實(shí)也不過是....
........... #%@^#&$^%*&$^)
考慮到我們寫module不過是為了設(shè)備驅(qū)動(dòng)或者
增加系統(tǒng)調(diào)用罷了.所以就有了兩個(gè)常用的宏.
DEV_MODULE和SYSCALL_MODULE
分別在/usr/include/sys/conf.h和sys/sysent.h中
也就是對DECLARE_MODULE的簡單包裝.
回想我們在linux下編譯一個(gè)模塊時(shí)無非是
gcc -DMODULE -D__KERNEL__ -DLINUX -O3 -c ....
可是在FreeBSD下就不是這么好辦了.看看
前面說的那兩個(gè)例子編譯時(shí)出來的那么一
大堆,我就先嚇壞了.
感謝上帝,不是沒一個(gè)人都要搞得那么清楚才能
編譯kld的.我們的Makefle關(guān)鍵在于.include
只要包含了bsd.kmod.mk,我們自己要作的事就是
SRCS= 源文件名
KMOD= 目標(biāo)模塊的名字
如果你是愛刨根問底的,請看/usr/share/mk
還是關(guān)于syscall的問題.
在sys/sysent.h中有定義
struct sysent {
int sy_narg;
sy_call_t *sy_call;
};
這分明是linux下面那個(gè)
sys_call_table么.
有區(qū)別的就是那個(gè)offset.
可以用offset=NO_SYSCALL來讓系統(tǒng)在載入的時(shí)候
自動(dòng)選擇syscall number.
回顧一下,我們的任務(wù)是要有一個(gè)
load_xxx函數(shù)來處理load和unload的情況
要有我們自己的調(diào)用.
最后SYSCALL_MODULE來注冊.
如果是設(shè)備模塊的話.
我們需要一張表
/usr/include/sys/conf.h中定義的
struct cdevsw {.....}
然后的過程和上面幾乎一模一.....
就這樣吧.強(qiáng)力推薦
1 http://thc.pimmel.com/files/thc/bsdkern.html
2 /usr/share/example/kld/