内核模块的加载.doc_第1页
内核模块的加载.doc_第2页
内核模块的加载.doc_第3页
内核模块的加载.doc_第4页
内核模块的加载.doc_第5页
已阅读5页,还剩3页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

2009-12-24 16:49:50 来自: 伊拉克蜜枣甜掉牙虚拟文件系统模块增加一个虚拟文件系统是非常简单的.假如你要开发一个新的文件系统或者支持现存的文件系统,就需要写一个模块作为接口.同样的,假如需要调试已经存在的文件系统,也需要那样一个接口.必须确定你的内核不支持目标文件系统.一个虚拟文件系统的模块的结构应该象如下定义:struct lkm_vfs MODTYPE lkm_type;int lkm_ver;char *lkm_name;u_long lkm_offset;struct vfsconf *lkm_vfsconf;和前面的例子差不多,我们也有个模块类型(LM_VFS),一个版本号,一个模块名和一个偏移值.在这个vfs模块的例子中,offset值是用不到的.最后我们需要一个指向vfsconf结构的指针,它包括了虚拟文件系统的操作向量以及一些其他信息(vfsconf结构在头文件/usr/include/sys/mount.h中定义).此结构通过MOD_VFS宏来初始化:MOD_VFS(nullfs, -1, &nullfs_vfsconf)我们看看上面的代码,第一个参数是我们的模块名,第二个参数offset,这个参数在我们的vfs模块中无关紧要(前面说过,可以不用).最后一个参数是我们的文件系统的结构.在你的模块的外部接口中,你必须调用vfs_opv_init_eXPlicit和vfs_opv_init_default来分配和初始化默认操作向量.因为文件系统被编译进内核,所以通过定义在/usr/src/sys/kern/vfs_conf.c里的vfs_opv_desc来在系统启动的时候装载.一个需要注意的是当用需要用ld程序来链接多个源代码文件来为modload提供目标文件时,你必须用-r标记来创建一个可重定位的目标文件.因为modload在把你的模块链接进内核的同时需要用到ld程序.可以用modload的-d标记来察看ld运行的内部参数.这儿是一个fs模块的完整代码 (nullmod.c):#include #include #include #include #include #include #include #include #include /* 文件系统的操作结构* 参考:/usr/src/sys/miscfs/nullfs/*/extern struct vfsops null_vfsops;extern struct vnodeopv_desc null_vnodeop_opv_desc;struct vfsconf nullfs_vfsconf = &null_vfsops, MOUNT_NULL, 9, 0, 0, NULL, NULL;/* 声明我们的模块结构,通过我们文件系统的模块名,offset和初始的vfsconf结构*/MOD_VFS(nullfs, -1, &nullfs_vfsconf)/* 我们的外部接口.我们初始化文件系统并且用到了DISPATCH宏,在此例中没有用到句柄*/intnullfsmod(lkmtp, cmd, ver)struct lkm_table *lkmtp;int cmd;int ver;vfs_opv_init_explicit(&null_vnodeop_opv_desc);vfs_opv_init_default(&null_vnodeop_opv_desc);DISPATCH(lkmtp, cmd, ver, lkm_nofunc, lkm_nofunc, lkm_nofunc)好,编译安装它:(一些其他的附加代码在/usr/src/sys/miscfs/nullfs里)e4gleopenbsd29# gcc -D_KERNEL -I/sys -c null_subr.ce4gleopenbsd29# gcc -D_KERNEL -I/sys -c null_vfsops.ce4gleopenbsd29# gcc -D_KERNEL -I/sys -c null_vnops.ce4gleopenbsd29# gcc -D_KERNEL -I/sys -c nullmod.ce4gleopenbsd29# ld -r -o nullfs.o null_vfsops.o null_vnops.o null_subr.o nullmod.oe4gleopenbsd29# modload -o nullfsmod -enullfsmod nullfs.oe4gleopenbsd29# modstatType Id Off Loadaddr Size Info Rev Module NameVFS 0 -1 e0b84000 0003 e0b860d0 2 nullfse4gleopenbsd29#ok,虚拟文件系统模块就说到这.其他类型的模块这些模块被用来执行一些预定的模块类型所没有定义的操作.在我这个例子中我们将为网络协议栈里加入控制代码,然后打印出我们接收到的tcp包的一些信息.当我们在书写其他类型的模块时,我们必须要完整的检查一遍,确定没有预定的操作.例如,同样的操作模块不能被加载两次.这等于我们在往内核中去写入模块.当然,我们都会在模块加载和卸载的控制函数里去控制.一个其他类型的模块结构象下面这样定义:struct lkm_misc MODTYPE lkm_type;int lkm_ver;char *lkm_name;u_long lkm_offset;同样,我们首先有一个模块的类型(在这个例子中试LM_MISC),然后是lkm的版本,再接着是模块名和offset的值.在我的这个例子中offset值没有用到,但在/usr/share/lkm/misc提供的例子中(增加一个系统调用)offset被用来在系统调用表里面标记一个新的系统调用的位置.用MOD_MISC宏来初始化该结构:MOD_MISC(tcpinfo)这里只有一个参数,指定了模块名.当我们的模块被加载后,该模块把tcp_input函数的指针改为我们制定的new_input函数.新的函数会打印出mbuf里的包头的一些信息,然后再调用原来的tcp_input函数.在做这些之前,我们一定要确定同类的模块没有被加载.对于这个模块一些值得注意的地方:首先运行这个模块时不适合传输大量的tcp包,printf()会变的很慢.大家试一下就知道.这个例子只是做测试之用,其实大家可以想想我们既然可以改变tcp协议栈里的函数指针,我们用模块来做一个tcp的内核后门也应该很容易,就留给大家思考吧,呵呵.第二,此代码原来是运行在freebsd之上的,稍微修改了一下而已,bsd系列的内核真是很相像.以下是该模块的完整代码(tcpmod.c):#include #include #include #include #include #include #include #include #include #include #include #include #include #include /* 我们将改变protosw结构中的TCP入口.*/extern struct protosw inetsw;/* 我们自定义的函数*/extern int lkmexists _P(struct lkm_table *);extern char *inet_ntoa _P(struct in_addr);static void new_input _P(struct mbuf *, .);static void (*old_tcp_input) _P(struct mbuf *, .);/* 声明我们的模块结构*/MOD_MISC(tcpinfo)/* 我们的句柄函数,用来加载和卸载模块.*/inttcpmod_handler(lkmtp, cmd)struct lkm_table *lkmtp;int cmd;int s;switch(cmd) case LKM_E_LOAD:/* 确定此模块是第一次加载使用*/if (lkmexists(lkmtp)return(EEXIST);/* 阻赛网络协议进程,我们把tcp_input函数指针改成我们自己的包装函数.*/s = splnet();old_tcp_input = inetsw2.pr_input;inetsw2.pr_input = new_input;splx(s);break;case LKM_E_UNLOAD:/* 当模块退出时返回原来的结构*/s = splnet();inetsw2.pr_input = old_tcp_input;splx(s);break;return(0);/* 我们的外部接口,没有做什么,用到了DISPATCH宏*/inttcpinfo(lkmtp, cmd, ver)struct lkm_table *lkmtp;int cmd;int ver;DISPATCH(lkmtp, cmd, ver, tcpmod_handler, tcpmod_handler, lkm_nofunc)/* 定义我们自己的包装的tcp_input函数.假如mbuf里有包头,则打印出网络接口接收到的包* 的总长度以及包的源地址.然后使原来的tcp_input函数正常运行.*/static voidnew_input(struct mbuf *m, .)va_list ap;int iphlen;struct ifnet *ifnp;struct ip *ip;va_start(ap, m);iphlen = va_arg(ap, int);va_end(ap);if (m-m_flags & M_PKTHDR) ifnp = m-m_pkthdr.rcvif;ip = mtod(m, struct ip *);printf(incoming packet: %d bytes , m-m_pkthdr.len);printf(on %s from %sn, ifnp-if_xname, inet_ntoa(ip-ip_src);(*old_tcp_input)(m, iphlen);return;好,我们编译安装它:e4gleopenbsd29# gcc -D_KERNEL -I/sys -c tcpmod.ce4gleopenbsd29# modload -o tcpinfo.o -etcpinfo tcpmod.o产生一些tcp连接,用dmesg来看看是否正常工作:e4gleopenbsd29# dmesg tail -3incoming packet: 1500 bytes on ne3 from 129.128.5.191incoming packet: 1205 bytes on ne3 from 129.128.5.191incoming packet: 52 bytes on ne3 fr

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论