Linux bsp驱动学习三:模块参数和模块之间通信

​ 为了增加模块的灵活性,可以给模块添加参数。模块参数可以控制模块的内部逻辑,从而使模块在不同的情况下,完成不同的功能,简单的说,模块参数就像函数的参数一样。

一、模块参数

​ 用户空间的应用程序可以接受用户的参数,设备驱动程序有时候也需要接受参数。

​ 例如一个模块可以实现两种相似的功能,这时可以传递一个参数到驱动模块,以决定其使用哪一种功能。参数需要在加载模块时指定,

例如 inmod xxx.ko param=1。

​ 可以用“module_param(参数名,参数数据类型,参数读写权限)”来为模块定义个参数

1
2
3
4
static long a = 1;
static int b = 1;
module_param(a, long, S_IRUGO);
module_param(b, int, S_IRUGO);

参数数据类型可以是 byte、short、ushort、int、uint、long、ulong、bool 和 charp(字符指针类型)。模块参数的类型中没有浮点类型,因为通常不在内核中使用浮点数。。

二、模块的文件格式ELF

​ 了解模块以何种格式存储在硬盘中,对于理解模块间怎样通信是非常有必要的。使用 file 命令可以知道 hello.ko 模块使用的是 ELF 文件格式,命令如下:

1
2
root@igkboard:~/workdir/01# file kernel_hello.ko 
kernel_hello.ko: ELF 32-bit LSB relocatable, ARM, EABI5 version 1 (SYSV), BuildID[sha1]=e83d8bb2113c7027d689b7ecc1a5eb995389532d, not stripped

下表描述的是ELF目标文件的总体结构。省去了ELF 一些繁琐的结构,把最主要的结构提取出来,形成了下表的文件基本结构图

ELF 文件基本结构图
ELF Header
.text
.data
其他
.Section Table
.symtab
其他
  • ELF Header 头位于文件的最前部。其包含了描述整个文件 的基本属性,例如 ELF 文件版本、目标机器型号、程序入 口地址等。
  • .text 表示代码段,存放文件的代码部分。
  • .data 表示数据段,存放已经初始化的数据等。
  • .Section Table 表描述了 ELF 文件包含的所有段的信息,例如每个段的段名、段的长度、在文件中的偏移、读写权限及段的其他属性。
  • .symtab 表示符号表。符号表是一种映射函数到真实内存地址的数据结构。其就像一个字典,其记录了在编译阶段,无法确定地址的函数。该符号表将在模块文件加载阶段,由系统赋予真实的内存地址。

三、模块之间的通信

​ 模块是为了完成某种特定任务而设计的。其功能比较单一,为了丰富系统的功能,所以模块之间常常进行通信。它们之间可以共享变量、数据结构,也可以调用对方提供的功能函数。

modules_temp

模块2的加载过程为:

      1. 使用insmod 模块2.ko加载模块2.
      2. 内核为模块2分配空间,然后将模块的代码和数据装入分配内存中。
      3. 内核发现符号表中有函数1,函数2可以导出,于是将其内存地址记录在内核符号表中

等到模块1加载进内核时,系统会执行以下操作:

  1. insmod命令会为模块分配空间,然后将模块的代码和数据装入内存中去。
  2. 内核在模块1的符号表(symtab)中发现一些未解析的函数,而这些函数的定义位于模块2的代码中。所以模块1会通过内核符号表,查找到相应的函数,并将函数地址填到模块1的符号表中。

​ 于是,通过模块1加载的过程之后,模块1就可以使用模块2提供的“函数1”和”函数2”了

四、模块中间的通信实例

​ 本实例通过两个模块介绍模块之间的通信。模块 add_sub 提供了两个导出函数 add_integer()和 sub_integer(),分别完成两个数字的加法和减法。模块 test 用来调用模块 add_sub 提供的两个方法,完成加法或者减法操作。

工程截图

image-20230418225107329

1、add_sub模块

​ 模块 add_sub 中提供了一个加法函数和一个减法函数,其 add_sub.c 文件如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/*********************************************************************************
* Copyright: (C) 2023 Noah<njy_roxy@outlook.com>
* All rights reserved.
*
* Filename: add_sub.c
* Description: This file
*
* Version: 1.0.0(2023年04月18日)
* Author: Noah <njy_roxy@outlook.com>
* ChangeLog: 1, Release initial version on "2023年04月18日 06时18分26秒"
*
********************************************************************************/


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

long add_integer(long a, long b) //函数返回a+b的和
{
return a+b;
}

long sub_integer(long a, long b) //函数返回a和b的差
{
return a-b;
}

EXPORT_SYMBOL(add_integer); //导出加法函数
EXPORT_SYMBOL(sub_integer); //导出减法函数

MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("NongJieYing <njy_roxy@outlook.com>");

add_sub.h:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/********************************************************************************
* Copyright: (C) 2023 Noah<njy_roxy@outlook.com>
* All rights reserved.
*
* Filename: add_sub.h
* Description: This file
*
* Version: 1.0.0(2023年04月18日)
* Author: Noah <njy_roxy@outlook.com>
* ChangeLog: 1, Release initial version on "2023年04月18日 06时32分48秒"
*
********************************************************************************/

#ifndef _ADD_SUB_H_
#define _ADD_SUB_H_

long add_integer(long a, long b);
long sub_integer(long a, long b);

#endif

对add_sub.c的Makefile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
KERNEL_DIR := /home/noah/imx6ull/bsp/kernel/linux-imx 
PWD :=$(shell pwd)
appname += add_sub
obj-m := $(appname).o
PRINC_INC = $(PWD)
EXTRA_CFLAGS += -I $(PRINC_INC)

modules:
$(MAKE) -I $(PRINC_INC) -C $(KERNEL_DIR) M=$(PWD) modules
@make clear

clear:
@rm -f *.o *.cmd *.mod *.mod.c
@rm -rf *~ core .depend .tmp_versions modules.order -f
@rm -f .*ko.cmd .*.o.cmd .*.o.d
@rm -f *.unsigned

clean:
@rm -f *.ko

2、test模块

test.c:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
/*********************************************************************************
* Copyright: (C) 2023 Noah<njy_roxy@outlook.com>
* All rights reserved.
*
*
* Filename: test.c
* Description: This file
*
* Version: 1.0.0(2023年04月18日)
* Author: Noah <njy_roxy@outlook.com>
* ChangeLog: 1, Release initial version on "2023年04月18日 06时39分31秒"
*
********************************************************************************/


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

static long a =1;
static long b =1;
static int AddOrSub = 1;
static __init int test_init(void)
{
long result = 0;
printk(KERN_ALERT "test init\n");
if(AddOrSub == 1)
{
result = add_integer(a, b);
}
else
{
result = sub_integer(a, b);
}
printk(KERN_ALERT "The %s result is %ld\n", AddOrSub==1?"Add":"Sub", result);
return 0;
}

static __exit void test_exit(void)
{
printk(KERN_ALERT "test exit\n");
}

module_init(test_init);
module_exit(test_exit);

module_param(a, long, S_IRUGO);
module_param(b, long, S_IRUGO);
module_param(AddOrSub, int, S_IRUGO);

//描述信息
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("NongJieYing <njy_roxy@outlook.com>");
MODULE_DESCRIPTION("The module for testing module params and EXPORT_SYMBOL");
MODULE_VERSION("V1.0");

test.c的Makefile:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
KERNEL_DIR := /home/noah/imx6ull/bsp/kernel/linux-imx 
PWD :=$(shell pwd)
appname += test
obj-m := $(appname).o
PRINC_INC = $(PWD)/
EXTRA_CFLAGS += -I $(PRINC_INC)
KBUILD_EXTRA_SYMBOLS =$(PWD)/../add_sub/Module.symvers
INCLUDES := $(PWD)

modules:
$(MAKE) -I $(PRINC_INC) -C $(KERNEL_DIR) M=$(PWD) modules
@make clear
clear:
@rm -f *.o *.cmd *.mod *.mod.c
@rm -rf *~ core .depend .tmp_versions modules.order -f
@rm -f .*ko.cmd .*.o.cmd .*.o.d
@rm -f *.unsigned

clean:
@rm -f *.ko

分别在各自的文件夹下执行make,各自复制文件到tftp文件夹下,然后由开发板下载至开发板内存内

1
2
3
4
5
6
7
# 开发板下
root@igkboard:~/workdir# tftp -gr add_sub.ko 192.168.0.202
root@igkboard:~/workdir# ls
01 02 add_sub.ko
root@igkboard:~/workdir# tftp -gr test.ko 192.168.0.202
root@igkboard:~/workdir# ls
01 02 add_sub.ko test.ko
1
2
3
4
5
6
7
8
9
10
11
# 开发板下
# 先加载add_sub.ko模块,test模块才能访问add_sub模块提供的导出函数
root@igkboard:~/workdir/04# insmod add_sub.ko
# 再使用insmod加载模块,并传递参数到模块中。参数AddOrSub=1表示a+b
root@igkboard:~/workdir/04# insmod test.ko a=4 b=5 AddOrSub=1
root@igkboard:~/workdir/04# dmesg | tail -5
[ 31.851546] fec 2188000.ethernet eth1: Link is Up - 100Mbps/Full - flow control off
[ 31.851643] IPv6: ADDRCONF(NETDEV_CHANGE): eth1: link becomes ready
[ 350.048344] test: no symbol version for add_integer
[ 350.048998] test init
[ 350.049022] The Add result is 9

测试成功