linux内核模块编写方法

来源:互联网 发布:网络文学评论停刊 编辑:程序博客网 时间:2024/06/05 11:30

目录

  • 一 内核模块结构
  • 二 模块编译测试
    • 1 编译
      • 11 Makefile 文件的书写
      • 12编译方法
    • 2 加载模块
    • 3 卸载模块
  • 三 模块参数
    • 1 c语言主函数的参数形式
    • 2 linux内核模块参数形式
  • 四 多模块同时编译
    • 1 程序
    • 2 编译结果
    • 3 加载卸载
  • 五 多文件编译成一个模块
    • 1 程序
    • 2 编译
    • 3 挂载卸载


一 内核模块结构

例子:

#include <linux/kernel.h>  //需要包含的内核头文件#include <linux/module.h>   //模块头文件//模块的入口函数  __init 是linux定义的关键字,表示这是一个入口函数static int __init hello_module_init(void){    printk("Hello,module is installed !\n");    return 0;}//模块出口函数  __exit linux定的关键字,表示出口static void __exit hello_module_cleanup(void){    printk("Good-bye, module was removed!\n");}//这两个函数分别是模块加载函数和模块卸载函数module_init(hello_module_init);module_exit(hello_module_cleanup);//表示模块许可声明,这个声明是必须的,如果没有这个声明,在加载模块是会出现内核污染警告MODULE_LICENSE("GPL");

二 模块编译测试

2.1 编译

2.1.1 Makefile 文件的书写

编译使用 makefile 文件编译,具体书写方法:

obj-m += module_001.o//内核所在目录KDIR:=/root/workdir/linux-3.5/all:    make -C $(KDIR) M=$(PWD) modules//调用内核编译时的makefile文件,便宜当前文件夹下的文件clean:    rm -f  *.o *.mod.o *.mod.c *.symvers *.markers *.order

2.1.2编译方法

[root@localhost 001]# makemake -C /root/workdir/linux-3.5/ M=/rootfs/root/driver/001 modulesmake[1]: Entering directory `/root/workdir/linux-3.5'  CC [M]  /rootfs/root/driver/001/module_001.o  Building modules, stage 2.  MODPOST 1 modules  CC      /rootfs/root/driver/001/module_001.mod.o  LD [M]  /rootfs/root/driver/001/module_001.komake[1]: Leaving directory `/root/workdir/linux-3.5'

2.2 加载模块

[root@TXM 001]#insmod /root/driver/001/module_001.ko[  113.885000] this is a init of my first module !

2.3 卸载模块

[root@TXM /]#rmmod /root/driver/001/module_001.ko[  126.075000] this is a exit of my first module !

三 模块参数

与c语言函数一样,模块也可以有函数

3.1 c语言主函数的参数形式

int main(int argc,char *argv[],char **envarg)

3.2 linux内核模块参数形式

//使用特定的函数向模块接口函数加载参数module_param(num, int, 0644);   //num传入参数,int参数类型,0644 参数权限(与文件权限一样)

参数类型有:
int
char
uint
charp
long
short
bool

//向模块接口函数传入数组module_param_array(a, int,&num, 0644);//a数组,int类型,num 个数(系统自动生成,一定加 & ),0644权限

例:

#include <linux/kernel.h>#include <linux/module.h>int num;int a[10];module_param(num,int,0644);module_param_array(a, int,&num, 0644);static int __init module_002_init(void){    int i;    printk("this is a init of my second module !\n");    printk("num = %d\n",num);    for(i=0;i<num;i++)           printk("%d\n",a[i]);    return 0;}static void __exit module_002_exit(void){    printk("this is a exit of my second module !\n");}module_init(module_002_init   );module_exit(module_002_exit);MODULE_LICENSE("GPL");

有参数时加载内核模块的方法:

[root@TXM 002]# insmod module_002.ko a=1,2,3[ 4504.475000] this is a init of my second module ![ 4504.475000] num = 3[ 4504.475000] 1[ 4504.475000] 2[ 4504.475000] 3

四 多模块同时编译

4.1 程序

模块1:

#include <linux/kernel.h>#include <linux/module.h>#include "print.h"int num;int a[10];module_param(num,int,0644);module_param_array(a, int,&num, 0644);static int __init module_001_init(void){    printk("this is a init of my first module !\n");    printk("num = %d\n",num);    print_me(num,a);    return 0;}void print_me(int num,int *a){    int i;    for(i=0;i<num;i++)           printk("%d\n",a[i]);}EXPORT_SYMBOL(print_me);static void __exit module_001_exit(void){    printk("this is a exit of my first module !\n");}module_init(module_001_init );module_exit(module_001_exit);MODULE_LICENSE("GPL");

模块2:

#include <linux/kernel.h>#include <linux/module.h>#include "print.h"int num;int a[10];module_param_array(a, int,&num,0644);static int __init tiny4412_hello_module_init(void){    printk("Hello, Tiny4412 module is installed !\n");    print_me(num,a);    return 0;}static void __exit tiny4412_hello_module_cleanup(void){    printk("Good-bye, Tiny4412 module was removed!\n");}module_init(tiny4412_hello_module_init);module_exit(tiny4412_hello_module_cleanup);DULE_LICENSE("GPL");

Makefile文件:

obj-m += module_002.o module_003.oKDIR:=/root/workdir/linux-3.5/all:    make -C $(KDIR) M=$(PWD) modules    rm -f  *.o *.mod.o *.mod.c *.symvers *.markers *.orderclean:    rm -f  *.o *.mod.o *.mod.c *.symvers *.markers *.order

4.2 编译结果

[root@localhost 002]# makemake -C /root/workdir/linux-3.5/ M=/rootfs/root/driver/002 modulesmake[1]: Entering directory `/root/workdir/linux-3.5'  CC [M]  /rootfs/root/driver/002/module_002.o  CC [M]  /rootfs/root/driver/002/module_003.o  Building modules, stage 2.  MODPOST 2 modules  CC      /rootfs/root/driver/002/module_002.mod.o  LD [M]  /rootfs/root/driver/002/module_002.ko  CC      /rootfs/root/driver/002/module_003.mod.o  LD [M]  /rootfs/root/driver/002/module_003.komake[1]: Leaving directory `/root/workdir/linux-3.5'rm -f  *.o *.mod.o *.mod.c *.symvers *.markers *.order

4.3 加载卸载

[root@TXM 002]# insmod module_003.ko a=1,2,3[ 4485.560000] module_003: Unknown symbol print_me (err 0)insmod: can't insert 'module_003.ko': unknown symbol in module, or unknown parameter[root@TXM 002]# insmod module_003.ko[ 4495.560000] module_003: Unknown symbol print_me (err 0)insmod: can't insert 'module_003.ko': unknown symbol in module, or unknown parameter

可见先加载 module_003 会出错,因为没有函数 print_me

[root@TXM 002]# insmod module_002.ko a=1,2,3[ 6160.900000] this is a init of my first module ![ 6160.900000] num = 3[ 6160.900000] 1[ 6160.900000] 2[ 6160.900000] 3[root@TXM 002]# insmod module_003.ko a=1,2,3[ 6166.995000] Hello, Tiny4412 module is installed ![ 6166.995000] 1[ 6166.995000] 2[ 6166.995000] 3
[root@TXM 002]# rmmod module_002.kormmod: can't unload 'module_002': Resource temporarily unavailable[root@TXM 002]# rmmod module_003.ko[ 6189.220000] Good-bye, Tiny4412 module was removed![root@TXM 002]# rmmod module_002.ko[ 6196.330000] this is a exit of my first module !

由上面运行结果可以看出,如果先卸载 module_002.ko 会出错,无法卸载,因为 module_003.ko 正在使用。


五 多文件编译成一个模块

5.1 程序

主函数

#include <linux/kernel.h>#include <linux/module.h>#include "print.h"int num;int a[10];module_param_array(a, int,&num, 0644);static int __init module_001_init(void){    printk("this is a init of my first module !\n");    printk("num = %d\n",num);    print_me(num,a);    return 0;}static void __exit module_001_exit(void){    printk("this is a exit of my first module !\n");}module_init(module_001_init   );module_exit(module_001_exit);MOD`LE_LICENSE("GPL");

子函数

#include "print.h"void print_me(int num,int *a){    int i;    for(i=0;i<num;i++)           printk("%d\n",a[i]);}

Makefile文件

obj-m += module_004_1.o/*  module_004_1.o相当于打包生成的文件  module_004.o & print.o 是依赖的文件*/module_004_1-objs:=module_004.o print.o#KDIR:=/lib/modules/$(shell uname -r)/buildKDIR:=/root/workdir/linux-3.5/all:    make -C $(KDIR) M=$(PWD) modules    rm -f  *.o *.mod.o *.mod.c *.symvers *.markers *.orderclean:    rm -f  *.o *.mod.o *.mod.c *.symvers *.markers *.order

5.2 编译

[root@localhost 003]# makemake -C /root/workdir/linux-3.5/ M=/rootfs/root/driver/003 modulesmake[1]: Entering directory `/root/workdir/linux-3.5'  CC [M]  /rootfs/root/driver/003/module_004.o  CC [M]  /rootfs/root/driver/003/print.o  LD [M]  /rootfs/root/driver/003/module_004_1.o  Building modules, stage 2.  MODPOST 1 modules  CC      /rootfs/root/driver/003/module_004_1.mod.o  LD [M]  /rootfs/root/driver/003/module_004_1.komake[1]: Leaving directory `/root/workdir/linux-3.5'rm -f  *.o *.mod.o *.mod.c *.symver *.markers *.order

5.3 挂载卸载

[root@TXM 003]# insmod module_004_1.ko a=1,2,3[ 9760.095000] this is a init of my first module ![ 9760.095000] num = 3[ 9760.095000] 1[ 9760.095000] 2[ 9760.095000] 3[root@TXM 003]# rmmod module_004_1.ko [10228.120000] this is a exit of my first module ![root@TXM 003]# 
原创粉丝点击