实验报告
实验题目:内核模块实现
姓名:
学号:
课程名称:操作系统
所在学院:信息科学与工程学院
专业班级:计算机
任课教师:
module_init(初始函数名);
module_exit(退出函数名 );
MODULE_LICENSE("GPL");//模块通用公共许可证
5、makefile文件内容基本格式
ifneq ($(KERNELRELEASE),)
obj-m:=xxx.o
else
KDIR:=/lib/modules/$(shell uname -r)/build
PWD:=$(shell pwd)
all:
make -C $(KDIR) M=$(PWD) modules
clean:
rm -rf *.o *.ko *.mod.c *.cmd *.markers *.order *.symvers .tmp_versions endif
说明:
1) KERNELRELEASE是在内核源码的顶层Makefile中定义的一个变量。
ifneq($(KERNELRELEASE),) 判断该变量是否为空。
2) KDIR := /lib/modules/$(shell uname -r)/build 是给KDIR这个变量赋值,值为当前linux运行的内核源码。
3) 当make的目标为all时,-C $(KDIR) 指明跳转到内核源码目录下读取那里的Makefile;M=$(PWD)表明然后返回到当前目录继续读入、执行当前的Makefile。
当从内核源码目录返回时,KERNELRELEASE已被被定义,kbuild也被启动去解析kbuild语法的语句,make将继续读取else之前的内容。
4) 我们可以把上述的Makefile文件作为一个模板,只需要改动obj-m := hello.o这条语句就可以了:obj-m=XXX.o。
4、进入管理员权限,cd到目录下。
输入如下命令:
5、输入make命令以编译:
6、编译成功后,输入insmod命令安装自己的内核模块:
7、查看内核模块:
可以看到自己的time模块安装成功。
8、输入dmesg命令,找到自己的内核模块,查看日志:
也可以用dmesg |grep time快速筛选到自己的内核模块。
9、卸载内核模块,输入如下命令即可:
可以再用lsmod命令查看内核模块,以验证是否删除。
(二)实现数据包过滤功能的简单内核模块
1、编写实现该模块的程序,并将该文件命名为PackageFilter.c
#include<linux/module.h>
#include<linux/kernel.h>
#include<linux/netdevice.h>
#include<linux/netfilter.h>
#include<linux/netfilter_ipv4.h>
#include<linux/ip.h>
#include<linux/init.h>
static struct nf_hook_ops nfhook;//定义nf_hook_ops结构体nfhook
static unsigned char *drop = "\x73\xef\xd3\x70";
//baidu的ip地址115.239.211.112
unsigned int hook_func( const struct nf_hook_ops *ops,
struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff*))
//钩子函数
{
struct iphdr *ip = ip_hdr(skb);//提取数据包ip首部
if(ip->saddr == *(unsigned int *)drop)//与定义ip地址进行比对
{
printk("DROP PACKET FROM %d.%d.%d.%d\n",drop[0],drop[1],drop[2],drop[3]);
//如果符合,丢弃
return NF_DROP;//返回丢弃信号
}
else//否则打印该网址
{
unsigned char *p = (unsigned char *)&(ip->saddr);
printk ("ALLOWED PACKET FROM %d.%d.%d.%d\n",p[0],p[1],p[2],p[3]);
return NF_ACCEPT;//返回接受信号
}
}
static int __init hook_init(void)//hook注册函数
{
nfhook.hook = hook_func;//关联定义的函数
nfhook.hooknum = NF_INET_PRE_ROUTING;//说明hook点
nfhook.pf = PF_INET;//说明处理协议是什么,ipv4为PF_INET
nfhook.priority = NF_IP_PRI_FIRST;//说明优先级
nf_register_hook(&nfhook);//注册hook
return 0;
}
static void __exit hook_exit(void)//退出该模块
{
nf_unregister_hook(&nfhook);
}
module_init(hook_init);
module_exit(hook_exit);
MODULE_LICENSE("Dual BSD/GPL");
2、编辑Makefile文件:
ifneq ($(KERNELRELEASE),)
obj-m:=PackageFilter.o
else
KDIR:=/lib/modules/$(shell uname -r)/build
PWD:=$(shell pwd)
all:
make -C $(KDIR) M=$(PWD) modules
clean:
rm -rf *.o *.ko *.mod.c *.cmd *.markers *.order *.symvers .tmp_versions
endif
3、将以上两个文件(PackageFilter.c和Makefile)放在同一个目录mykernel下。
4、进入管理员权限,cd到目录下。
输入如下命令:
5、输入make命令以编译:
6、编译成功后,输入insmod命令安装自己的内核模块,再查看内核模块:
可以看到自己的time模块安装成功:
7、输入dmesg命令,找到自己的内核模块,查看日志:
(截取部分结果)8、卸载内核模块,输入如下命令即可:
可以再用lsmod命令查看内核模块,以验证是否删除。
五、实验数据(现象)处理分析
实验现象在上面的实验步骤中已有详细说明,这里只给出实验结果:
1、输出内核时间
2、数据包过滤
六、实验结论
通过本次实验,我基本熟悉了Linux内核模块实现流程——先编写相关模块代码,编写makefile文件,编译,安装模块,查看模块,查看日志,卸载模块。
同时对Netfilter 框架有了一定的了解。
明白了Netfilter的基本工作原理,和hook函数的一些简单的编写。
同时验证了编写的内核模块程序,完成了实验要求的目标。