内核模块0.1版本
这个例子是照着《linux 内核编程》Claudia Salzberg Rodriguez 等著 陈莉君译书上的例子写的,修正了书中例子中的部分错误.
/*************************************************************************
> File Name: hellomod.c
> Author: guoqingyao
> Mail: stepbystepto@163.com
> Created Time: 2016年07月06日 星期三 20时19分57秒
************************************************************************/
#include<linux/module.h>
#include<linux/kernel.h>
#include<linux/init.h>
MODULE_LICENSE("GPL"); //原书是 : #MODULE_LICENCE("GPL"); 有编译错误,语法和拼写都有问题.
static int __init lkp_init(void )
{
printk("<1> Hello world ! from kernel space!");
return 0;
}
static void __init lkp_exit(void )
{
printk("<1> Byebye world ! from kernel space!");
return ;
}
module_init(lkp_init);
module_exit(lkp_exit);
对应的Makefile文件如下:
obj-m += hellomod.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) modules
clean:
rm -rf *.o *.ko *.mod.c *.mod.o modules.* Mod*
然后在超级用户权限下面:
root@dotheright# make clean
root@dotheright# make
root@dotheright# insmod hellomod.ko
root@dotheright# lsmod | head #查看你的模块信息
root@dotheright# rmmod hellomod #这里会出现卸载不掉的现象
root@dotheright# tail /var/log/kern.log #查看内核打印
如何解决模块卸载不掉的问题
- 使用的内核,在编译的时候,使能了CONFIG_MODULE_FORCE_UNLOAD ,然后使用 rmmod -f XXX
- 将模块的状态设置为0;
代码如下:
/*************************************************************************
> File Name: mymod.c
> Author: guoqingyao
> Mail: stepbystepto@163.com
> Created Time: 2016年10月04日 星期三 11时10分57秒
************************************************************************/
#include<linux/init.h>
#include<linux/module.h>
#include<linux/kernel.h>
#include<linux/list.h>
MODULE_AUTHOR("GuoQingyao");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("deal module can not be removed");
static int __init mymod_init(void)
{
struct module *pmod;
// 打印本模块的模块名和模块状态
printk(KERN_ALERT"[insmod mymod] name:%s state:%d\n",THIS_MODULE->name,THIS_MODULE->state);
// 遍历模块列表,查找target模块
list_for_each_entry(pmod,THIS_MODULE->list.prev,list)
{
if(strcmp(pmod->name,"mymod") ==0)
{
// 模块名、模块状态、引用计数
printk(KERN_ALERT"init name:%s state:%d refcnt:%u ",pmod->name,pmod->state,module_refcount(pmod));
// 把target的引用计数置为0
pmod->state =0;
// 再看看 模块名、状态、引用计数
printk(KERN_ALERT"modified name:%s state:%d refcnt:%u\n",pmod->name,pmod->state,module_refcount(pmod));
}
}
return 0;
}
static void __exit mymod_exit(void)
{
printk(KERN_ALERT"[rmmod mymod] name:%s state:%d\n",THIS_MODULE->name,THIS_MODULE->state);
}
module_init(mymod_init);
module_exit(mymod_exit);
对应的Makefile
obj-m += mymod.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) modules
clean:
rm -rf *.o *.ko *.mod.c *.mod.o modules.* Mod*
对应的操作记录:
root@dotheright:/home/dotheright/mylovelycodes/linux_c/kernel# make
make -C /lib/modules/4.4.0-38-generic/build M=/home/dotheright/mylovelycodes/linux_c/kernel modules
make[1]: Entering directory '/usr/src/linux-headers-4.4.0-38-generic'
Building modules, stage 2.
MODPOST 1 modules
make[1]: Leaving directory '/usr/src/linux-headers-4.4.0-38-generic'
root@dotheright:/home/dotheright/mylovelycodes/linux_c/kernel# insmod mymod
insmod: ERROR: could not load module mymod: No such file or directory
root@dotheright:/home/dotheright/mylovelycodes/linux_c/kernel# insmod mymod.ko
root@dotheright:/home/dotheright/mylovelycodes/linux_c/kernel# lsmod | head
Module Size Used by
mymod 16384 0
hellomode 12288 0
rndis_host 16384 0
cdc_ether 16384 1 rndis_host
usbnet 45056 2 rndis_host,cdc_ether
rfcomm 65536 4
bnep 20480 2
arc4 16384 2
snd_hda_codec_conexant 20480 1
root@dotheright:/home/dotheright/mylovelycodes/linux_c/kernel# rmmod mymod
root@dotheright:/home/dotheright/mylovelycodes/linux_c/kernel# tail -4 /var/log/kern.log
Oct 4 12:21:47 dotheright kernel: [73360.963002] [insmod mymod] name:mymod state:1
Oct 4 12:21:47 dotheright kernel: [73360.963009] init name:mymod state:1 refcnt:1
Oct 4 12:21:47 dotheright kernel: [73360.963012] modified name:mymod state:0 refcnt:1
Oct 4 12:22:06 dotheright kernel: [73380.012431] [rmmod mymod] name:mymod state:2
root@dotheright:/home/dotheright/mylovelycodes/linux_c/kernel#