第四章 Linux内核模块

注:内容大多摘自《Linux设备驱动开发详解》(第2版)

Linux内核模块

1.1 简介

1.特点:

  • 模块本身不被编译入内核映像,从而控制了内核的大小;
  • 模块一旦被加载,它就和内核中的其他部分完全一样。

2.模块程序结构
(1)模块加载函数(一般需要)
(2)模块卸载函数(一般需要)
(3)模块许可证声明(必须)
(4)模块参数(可选)
(5)模块导出符号(可选)
(6)模块作者等信息声明(可选)

3.模块的加载,卸载,查看:

  • 加载:insmod命令
    模块加载后,在/sys/module/目录下面将出现以此模块名命名的目录。
  • 卸载:rmmod命令
  • 查看:lsmod命令,查看所有加载的内核模块

4.printk函数
内核模块中用于输出的函数是内核空间的printk()而非用户空间的printf(),printk与printf用户相似,但前者可定义输出级别。printk可作为一种最基本的内核调试手段。参考:printk 使用方法
备注:测试模块例子时,终端没能输出printk的输出信息,可以通过执行dmesg命令查看。参考:printk 无法输出到控制台

1.2,简单模块例子

1,模块代码(创建hello.c):

# include <linux/init.h>
# include <linux/module.h>

static int hello_init(void)
{
    printk(KERN_EMERG "Hello World enter\n");
    return 0;
}

static void hello_exit(void)
{
    printk(KERN_EMERG "Hello World exit\n");
}

module_init(hello_init);
module_exit(hello_exit);

MODULE_LICENSE("Dual BSD/GPL");

2,编译代码 (创建Makefile文件):

## 执行uname -r 输出为 4.2.0-16-generic
KVERS = $(shell uname -r)

# Kernel modules
obj-m +=hello.o

#Specify flags for the module compliation

build: kernel_modules

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

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

3,在模块代码和Makefile的当前目录下执行make命令,生成hello.ko,调用insmod hello.ko挂载该模块(可执行lsmod查看是否挂载成功),调用rmmod hello卸载该模块。执行dmesg查看printk的输出信息。

1.3 模块声明与描述

MOUDLE_AUTHOR(author);    #作者
MOUDLE_DESCRIPTION(description);    #描述
MOUDLE_VERSION(version);    #版本
MODULE_DEVICE_TABLE(table_info);    #设备表
MODULE_ALIAS(alternate_name);    #别名

执行modeinfo <模块名>可以获取模块信息,如modinfo hello.ko。

1.4 模块参数

用module_param(参数名,参数类型,参数读/写权限)为模块定义一个参数,例子如下:

static char* book_name = "dissecinting Linux Device Driver";
static int num = 4000;
module_param(book_name, charp, S_IRUGO);
module_param(num, int, S_IRUGO);

# 装载是执行命令:insmod param.ko book

参数类型可以是byte, short, ushort, int, uinit, long, ulong, charp(字符指针), bool或invbool(布尔的反),编译时会将module_param中声明的类型和变量定义的类型进行比较,判断是否一致。

模块加载后,在/sys/module/目录下面将出现以此模块名命名的目录。当读写权限为0时,表示此参数不存在sysfs文件系统下对应的文件节点;如果不为0,在此模块目录下回出现parameter目录,包含一系列以参数命名的文件节点。权限在include/linux/stat.h中有定义

使用 S_IRUGO 参数可以被所有人读取, 但是不能改变; S_IRUGO|S_IWUSR 允许 root 来改变参数. 注意, 如果一个参数被 sysfs 修改, 你的模块看到的参数值也改变了, 但是你的模块没有任何其他的通知. 你应当不要使模块参数可写, 除非你准备好检测这个改变并且因而作出反应。
(参考:Linux之module_param()函数学习

1.5 模块的使用

嵌入式产品一般不需要建立模块间依赖关系,所以modprobe可以不要,一般也不需要卸载模块,所以rmmod也可以不要,但insmod是必须的(在Android设备中尝试了insmod,rmmod,modinfo,lsmod等命令,都有存在,而modprobe不存在)。一般而言,产品在启动过程中应该加载模块,在嵌入式产品Linux的启动过程中,最简单的修改方法是修改启动过程的rc脚本(可能是/init.rc文件),增加insmod /…/xxx.ko这样的命令。用busybox做出的文件系统,通常修改etc/init.d/rcS文件。

1.6 导出符号

暂时不知道怎么使用,类似外部函数
参考:导出符号的意义

1.7 附录:

1,Hello World代码:
(1)hello.c代码

# include <linux/init.h>
# include <linux/module.h>

static int hello_init(void)
{
    printk(KERN_EMERG "Hello World enter\n");
    return 0;
}

static void hello_exit(void)
{
    printk(KERN_EMERG "Hello World exit\n");
}

module_init(hello_init);
module_exit(hello_exit);

MODULE_LICENSE("Dual BSD/GPL");

(2)Makefile文件

## 执行uname -r 输出为 4.2.0-16-generic
KVERS = $(shell uname -r)

# Kernel modules
obj-m +=hello.o

#Specify flags for the module compliation

build: kernel_modules

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

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

2,模块参数例子代码:
(1)文件:book.c

# include <linux/init.h>
# include <linux/module.h>

static char* book_name = "dissecinting Linux Device Driver";
static int num = 4000;

static int hello_init(void)
{
    printk(KERN_EMERG "book name:%s\n", book_name);
    printk(KERN_EMERG "book num:%d\n", num);
    return 0;
}

static void hello_exit(void)
{
    printk(KERN_EMERG "Hello World exit\n");
}

module_init(hello_init);
module_exit(hello_exit);
module_param(book_name, charp, S_IRUGO);
module_param(num, int, S_IRUGO);

MODULE_LICENSE("Dual BSD/GPL");

(2)文件:Makefile

KVERS = $(shell uname -r)

# Kernel modules
obj-m +=book.o

#Specify flags for the module compliation


build: kernel_modules

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

clean:
    make -C /lib/modules/$(KVERS)/build M=$(CURDIR) clean
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值