内核模块学习

linux内核的框架很大,组件很多,如果把所有东西全编译进内核,内核会很大,如果我们要进行修改时,还要重新编译内核,耗时费力.linux的模块机制解决了这样的问题,模块本身不编译进内核,控制了内核的大小,模块一旦被加载,和内核中其他部分一样.

一.简单的例子

说的多,不如贴代码,一个简单的例子程序如下:

/*bike.c*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>


static char * bike_name = "mobike";
module_param(bike_name,charp,S_IRUGO);

static int bike_num = 3000;
module_param(bike_num,int,S_IRUGO);

static int __init bike_init(void)
{
    printk(KERN_INFO "hello bike module\n");
    printk(KERN_INFO "bike-name:%s\n",bike_name);
    printk(KERN_INFO "bike_num:%d\n",bike_num);
    return 0;
}
module_init(bike_init);

static void __exit bike_exit(void)
{
    printk(KERN_INFO "bike module exit\n");
}
module_exit(bike_exit);

MODULE_AUTHOR("Trice");
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("A simple program for testing kernel module");
MODULE_VERSION("V1.0");

一个内核模块主要由:
1.模块加载函数
2.模块卸载函数
3.模块声明
4.模块参数(可选)
5.模块作者(可选)


模块加载函数

static int __init bike_init(void)
{
    printk(KERN_INFO "%s\n",bike_name);
    printk(KERN_INFO "%d\n",bike_num);
    return 0;
}
module_init(bike_init);

linux中,标识为__init的函数如果直接编译进内核,连接时会放在.init.text段,初始化时,内核会调用这些__init函数,完成后释放.类似数据可以标识为__initdata.
所以bike_init以__init标识,加载时用module_init指定.


模块卸载函数

static void __exit bike_exit(void)
{
    printk(KERN_INFO "bike module exit\n");
}
module_exit(bike_exit);

卸载函数用__exit标识,用module_exit指定


模块声明

MODULE_AUTHOR("Trice");
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("A simple program for testing kernel module");
MODULE_VERSION("V1.0");

声明一些信息,其中MODULE_LICENSE("GPL v2");声明模块的许可权限.


模块参数

static char * bike_name = "mobike";
module_param(bike_name,charp,S_IRUGO);

static int bike_num = 3000;
module_param(bike_num,int,S_IRUGO);

使用module_param(参数名,类型,参数读写权限),charp表示字符指针,传递时采用insmod 模块名 参数名=参数值,S_IRUGO,表示读,U->user G->group O->other.


二.模块的编译

上面的bike.c可以用下面的Makefile进行编译

KVERS = $(shell uname -r)

#kernel module
obj-m += bike.o


build:kernel_modules

kernel_modules:
    make -C /lib/modules/$(KVERS)/build M=$(CURDIR) modules

clean:
    make -C /lib/modules/$(KVERS)/build M=$(CURDIR) clean

obj-m += bike.o这种在内核编译中很常见,意思把bike.c编成模块,进入相应目录使用里面Makefile进行编译,M=$(CURDIR)指定目标.
如果有多个文件可以使用:

obj-m := xx.o
xx-objs := file1.o file2.o

三.测试结果

huang@ubuntu:~/test$ ls
bike.c  Makefile
huang@ubuntu:~/test$ 
huang@ubuntu:~/test$ 
huang@ubuntu:~/test$ make
make -C /lib/modules/3.16.0-30-generic/build M=/home/huang/test modules
make[1]: Entering directory `/usr/src/linux-headers-3.16.0-30-generic'
  CC [M]  /home/huang/test/bike.o
  Building modules, stage 2.
  MODPOST 1 modules
  CC      /home/huang/test/bike.mod.o
  LD [M]  /home/huang/test/bike.ko
make[1]: Leaving directory `/usr/src/linux-headers-3.16.0-30-generic'
huang@ubuntu:~/test$ 
huang@ubuntu:~/test$ 
huang@ubuntu:~/test$ ls
bike.c   bike.mod.c  bike.o    modules.order
bike.ko  bike.mod.o  Makefile  Module.symvers
huang@ubuntu:~/test$ 
huang@ubuntu:~/test$ sudo insmod bike.ko
huang@ubuntu:~/test$ lsmod | grep bike
bike                   12665  0 
huang@ubuntu:~/test$ 
huang@ubuntu:~/test$ dmesg | tail -3
[19695.556447] hello bike module
[19695.556453] bike-name:mobike
[19695.556456] bike_num:3000
huang@ubuntu:~/test$ 
huang@ubuntu:~/test$ 
huang@ubuntu:~/test$ sudo rmmod bike
huang@ubuntu:~/test$ 
huang@ubuntu:~/test$ lsmod | grep bike
huang@ubuntu:~/test$ 
huang@ubuntu:~/test$ dmesg | tail -1
[19804.797345] bike module exit
huang@ubuntu:~/test$ sudo insmod bike.ko bike_name=ofo bike_num=666
huang@ubuntu:~/test$ dmesg | tail -3
[20692.083907] hello bike module
[20692.083913] bike-name:ofo
[20692.083915] bike_num:666
huang@ubuntu:~/test$ sudo rmmod bike;dmesg | tail -1
[20760.653996] bike module exit

insmod rmmod lsmod分别用于装载 卸载 查看模块
dmesg用于显示打印信息
tail -n显示最后n行

四.总结

内核模块只是把.c文件编译成.ko文件,其实就是一种目标文件的形式,然后在装载时,由内核实现模块的链接运行,同时,在内核加载和卸载的过程中,会通过函数回调用户定义的模块入口函数和模块出口函数,实现相应的功能。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容