Linux中多个.c文件编译为一个模块.ko

本文介绍了如何将多个.c文件(如exp.c, exps.c)编译成一个Linux内核模块(.ko文件)。在exp.c中使用module_init和module_exit,而exps.c包含工具函数。通过在Makefile中指定模块名和依赖文件,可以成功编译并插入模块。在遇到文件名与模块名冲突时,需要选择不同的模块名以避免错误。" 83025460,5668834,Wi-Fi模块与TCP服务器数据交互,"['嵌入式开发', '无线通信', '服务器开发', '编程语言', '硬件交互']

例如现在有三个文件:

exp.c

exps.c

exp.h

这是目前做实验的代码,其中exps中是工具函数,其内容被exp.c调用,exp.h是exps.c文件中函数的声明以及一些结构体的定义。

下面介绍将exp.c与exps.c编译为一个模块ex.ko,以及在这个过程中遇到的一系列问题。

由于exps.c中是一些工具函数,所以在exps.c中不需要module_init、module_exit等来进行修饰,而exp.c要调用exps.c,并且里面含有模块的入口函数和出口函数,所以在exp.c中使用module_init、module_exit等模块结构。

一个模块只有一个入口和出口,所以只有一对module_init、module_exit,同时要添加上MODULE_LICENSE("GPL")

实验代码不方便贴出来,但是方法已经过真机测试,现在在我的虚拟机上随便写几个函数来演示一下:

exp.c:

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include "exp.h"

extern void exps_init(int e);

static int table_init(void)
{
	printk("TABLE: table init \n");
	exps_init(50);   
	return 0;
}

static void table_exit(void)
{
	printk("TABLE: table exit \n");
}

module_init(table_init);
module_exit(table_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Me");
MODULE_DESCRIPTION("module test");

extern导入符号是必要的,测试了如果不导入符号,会报如下错误:

error: implicit declaration of function ‘exps_init’ [-Werror=implicit-function-declaration]

即使这句extern 写在exp.h中也不行。

exps.c:

#include "exp.h"
#include <linux/kernel.h>

void print(int e)
{
	printk("parameter is %d \n",e);
}

void exps_init(int e)
{
	printk("hello, this is exps \n");
	print(e);	
}

在exps.c中,符号exps_init会被exp.c调用,这里既可以使用EXPORT_SYMBOL来导出这个符号,也可以不使用EXPORT_SYMBOL,测试了都没有问题。

exp.h:

#ifndef _LINUX_EXP_COMMON_H_
#define _LINUX_EXP_COMMON_H_

void exps_int(int e);

#endif

Makefile:

ifneq ($(KERNELRELEASE),)
obj-m:=ex.o
ex-objs:=exp.o exps.o
else
 
#generate the path
CURRENT_PATH:=$(shell pwd)
CONFIG_MODULE_SIG = n
#the absolute path
LINUX_KERNEL_PATH:=/lib/modules/$(shell uname -r)/build

#complie object
default:
	make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules
clean:
	make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) clean
endif

Makefile是关键,首先 obj-m指定模块名,然后再根据模块名-objs:=依赖的文件。

最开始我想将模块名设置为exp,但是和我的文件重名了,这时候编译虽然成功了,但是插入模块会报如下错误:

[ 2045.410335] exp: module license 'unspecified' taints kernel.
[ 2045.410338] Disabling lock debugging due to kernel taint

所以我不能选择exp或者exps作为模块名~

依赖文件不需要顺序,比如既可以是:

ex-objs:=exp.o exps.o

也可以是:

ex-objs:=exps.o exp.o

使用make编译得到如下内容:

insmod 插入模块后,dmesg就可以得到想要的信息:

 

多个文件:

多个文件也是一样,比如这里我再增加了一个expss.c文件,该文件中函数expss_init被exps.c中函数调用:

此时exps.c:

#include "exp.h"
#include <linux/kernel.h>

extern int expss_init(int e);

void print(int e)
{
	printk("parameter is %d \n",e);
}

void exps_init(int e)
{
	printk("hello, this is exps \n");
	e = expss_init(e);
	print(e);	
}

expss.c:

#include <linux/kernel.h>
#include "exp.h"

int expss_init(int e)
{
	return (e+10);
}

Makefile:

ifneq ($(KERNELRELEASE),)
obj-m:=ex.o
ex-objs:=expss.o exps.o exp.o 
else
 
#generate the path
CURRENT_PATH:=$(shell pwd)
CONFIG_MODULE_SIG = n
#the absolute path
LINUX_KERNEL_PATH:=/lib/modules/$(shell uname -r)/build

#complie object
default:
	make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules
clean:
	make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) clean
endif

编译出文件如下:

插入模块运行如下:

评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值