linux内核模块编写方法

目录


一 内核模块结构

例子:

#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]# make
make -C /root/workdir/linux-3.5/ M=/rootfs/root/driver/001 modules
make[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.ko
make[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.o

KDIR:=/root/workdir/linux-3.5/
all:
    make -C $(KDIR) M=$(PWD) modules
    rm -f  *.o *.mod.o *.mod.c *.symvers *.markers *.order
clean:
    rm -f  *.o *.mod.o *.mod.c *.symvers *.markers *.order

4.2 编译结果

[root@localhost 002]# make
make -C /root/workdir/linux-3.5/ M=/rootfs/root/driver/002 modules
make[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.ko
make[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.ko
rmmod: 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)/build
KDIR:=/root/workdir/linux-3.5/

all:
    make -C $(KDIR) M=$(PWD) modules
    rm -f  *.o *.mod.o *.mod.c *.symvers *.markers *.order
clean:
    rm -f  *.o *.mod.o *.mod.c *.symvers *.markers *.order

5.2 编译

[root@localhost 003]# make
make -C /root/workdir/linux-3.5/ M=/rootfs/root/driver/003 modules
make[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.ko
make[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]# 
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值