linux内核编程(hello world)
Linux可加载内核模块是 Linux 内核的最重要创新之一。它们提供了可伸缩的、动态的内核。其它开发者可以不用重新编译整个内核便可以开发内核层的程序,极大方便了驱动程序等的开发速度。
本系列文章主要是记录个人从hello world开始,通过学习linux内核基本编程操作,再对ipvs负载均衡器源码进行初步学习分析;最后,基于netfilter机制(其实是iptables的xtables-plugin)完成一个报文转发工具,xt_GTPU工具。
基础环境:腾讯云虚拟机(最便宜的那种),ubuntu 14.04
hello world!
内核编程,当然最开始也是要从经典的hello world开始。
目录结构如下:
feiqianyousadeMacBook-Pro:helloworld yousa$ tree
.
├── Makefile
└── helloworld.c
0 directories, 2 files
示例代码(命名此文件为helloworld.c)
#include <linux/init.h>
#include <linux/module.h>
static int helloworld_init(void) {
printk(KERN_INFO "hello world!\n");
return 0;
}
static int helloworld_exit(void) {
printk(KERN_INFO "see you.\n");
return 0;
}
module_init(helloworld_init);
module_exit(helloworld_exit);
makefile文件(命名此文件为Makefile)
KERNEL_VER = $(shell uname -r)
# the file to compile
obj-m += helloworld.o
# specify flags for the module compilation
EXTRA_CFLAGS = -g -O0
build: kernel_modules
kernel_modules:
#make -C /lib/modules/`uname -r`/build M=$(PWD) modules
make -C /lib/modules/$(KERNEL_VER)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(KERNEL_VER)/build M=$(PWD) clean
编译好之后执行make即可;编译成功之后,会有一个helloworld.ko文件,使用insmod命令加载模块
sudo insmod helloworld.ko
使用lsmod | grep hello
可以看到已经加载了该内核模块
ubuntu@VM-7-212-ubuntu:~/kernel-code/kernel-netfilter-sample-code/helloworld$ lsmod | grep hello
helloworld 16384 0
使用dmesg | tail -n 20可以查看hello world相应的打印
内核模块
内核模块(linux kernel module–LKM)与直接编译到内核或典型程序的元素有根本区别。典型的程序有一个 main 函数,而内核模块 包含 entry 和 exit 函数。当向内核插入模块时,调用 entry 函数,从内核删除模块时则调用 exit 函数。因为 entry 和 exit 函数是用户定义的,所以存在 module_init 和 module_exit 宏,用于定义这些函数属于哪种函数和告知内核在加载/卸载对应模块时需要执行哪个函数。内核模块还包含一组必要的宏和一组可选的宏,用于定义模块的许可证、模块的作者、模块的描述等等。
(代码中的entry函数就是static int helloworld_init(void)
,exit函数是static int helloworld_exit(void)
,它们最后使用module_init 和 module_exit 宏告知内核加载时调用helloworld_init函数和退出时调用helloworld_exit函数)
在2.6版本之后(当前基本都是linux内核2.6以后的了吧……),可以通过insmod/rmmod等命令操作内核,其主要命令如下:
- insmod: 将模块插入内核中,使用方法:#insmod XXX.ko
- rmmod: 将模块从内核中删除,使用方法:#rmmod XXX.ko
- lsmod: 列表显示所有的内核模块,可以和grep指令结合使用。使用方法:#lsmod | grep XXX
- modprobe: modprobe可载入指定的个别模块,或是载入一组相依赖的模块。modprobe会根据depmod所产生的依赖关系,决定要载入哪些模块。若在载入过程中发生错误,在modprobe会卸载整组的模块。依赖关系是通过读取 /lib/modules/2.6.xx/modules.dep得到的。而该文件是通过depmod 所建立。
- modinfo: 查看模块信息。使用方法:#modinfo XXX.ko
源码信息
代码github
https://github.com/Miss-you/kernel-netfilter-sample-code
其中helloworld是在helloworld目录下
遇到的问题
make: * /lib/modules/4.4.0-53-generic/build: 没有那个文件或目录。 停止。
参照链接