实践2.2 内核模块编译
1.模块代码的编写
模块构造函数:
module_init()
即执行insmod或modprobe指令加载内核模块时会调用的初始化函数。
模块析构函数:
module_exit()
即执行rmmod指令卸载模块时调用的函数。
模块许可声明:
MODULE_LICENSE()
告诉内核该程序使用的许可证,不然在加载时它会提示该模块污染内核。一般会写GPL。
头文件:
<linux/module.h>,必须包含此文件;
<linux/kernel.h>,包含常用的内核函数;
<linux/init.h>,包含宏_init和_exit,允许释放内核占用的内存。
编写代码:
//test_sche.c
#include <linux/init.h>
#include <linux/module.h>
MODULE_LICENSE("Dual BSD/GPL");
static char *name="YJX";
static int __init name_init(void)
{
printk("***Hello World!***
");
printk("***Hello %s!***
",name);
return 0;
}
static void __exit name_exit(void)
{
printk(KERN_INFO"Name module exit
");
}
module_init(name_init);
module_exit(name_exit);
module_param(name,charp,S_IRUGO);
MODULE_AUTHOR("YJX");
MODULE_VERSION("v1.0);
MODULE_DESCRIPTION(“A simple module for testing pirntk and module params:");
编译模块-Makefile
//Makefile
obj-m := test_sche.o
PWD := $(shell pwd)
KDIR := /lib/modules/3.2.0-29-generic-pae/build
all:
make -C $(KDIR) M=$(PWD) modules
clean:
make -C $(KDIR) M=$(PWD) clean
第一行:自己写的.c的文件名+”.o”。
第三行的KDIR后面要写自己的内核版本对应的内核源码包地址.
如何查看?
uname -r
解释一下make命令:
make -C $(KDIR) 指明跳转到内核源码目录下读取那里的Makefile
M=$(PWD) 表明返回到当前目录继续执行当前的Makefile。
make结果:
make执行之后会出现很多文件:
加载模块
sudo insmod test_sche.ko
测试模块
dmesg
卸载模块
sudo rmmod test_sche.ko
测试结果:
1.加载后:
2.卸载后:
读取进程链表:
代码:
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/sched.h>
static struct task_struct *pcurrent;
static int __init print_init(void)
{
pirntk(KERN_INFO"print current task info
");
printk("pid tgid prio state
");
for_each_process(pcurrent){
printk("%d ",purrent->pid);
printk("%d ",purrent->tgid);
printk("%d ",purrent->prio);
printk("%ld
",purrent->state);
}
return 0;
}
static void __exit print_exit(void)
{
printk(KERN_INFO "Finished
");
}
module_init(print_init);
module_exit(print_exit);
编译运行加载后,测试结果为: