模块符号的导入与导出以及使用模块规避GPL传染性

【BSP开发学习6】模块符号的导入与导出以及使用模块规避GPL传染性_与光同程的博客-CSDN博客

文章目录
讨厌的GPL传染性
关于符号导出
规避GPL的方式


实践
讨厌的GPL传染性
依据GPL 的相关规定,如果原始授权人采用GPL来发布自己的作品,那么无论该作品的任何衍生作品,都要遵从GPL 的规则,尽管你对于该衍生作品拥有著作权,但是你也不可以因此认为它是你的心血而另立新规,可谓“子子孙孙无穷尽也”。也即规则的“传染性”。GPL 下的软件,是允许作为学习来复制使用的。但当基于该软件源代码开发出新作品,而该作品并非是自由软件的一部分,或基于其产生的衍生作品,它是独立的,不同于该自由软件的部分,即不同作品,那么它将不受GPL 的约束;但是,一旦你把它同该自由软件作为一个整体一同发布,它就会被“传染”上GPL 的属性,从而不得不遵守GPL 的规矩了。也即作品整体的“传染性”。如果软件是非开源的,那么是不可以把GPL 下的软件源代码使用到该的程序中的。但是,倘若你非得使用该开源代码,那么你只有把你原先的非开源的代码贡献给社区了,也即GPL 下的开源性“传染”了非开源代码。

关于符号导出
Linux内核头文件提供了一个方便的方法用来管理符号的对模块外部的可见性,因此减少了命名空间的污染(命名空间的名称可能会与内核其他地方定义的名称冲突),并且适当信息隐藏。

linux内核是一个大程序,当动态加载进入一个模块时,这个模块还是内核的一部分。所以可以像一个工程项目那样,将函数导出到内核符号表中,再在需要调用的外部声明为 extern关键字 ,就可以方便的调用了

规避GPL的方式
Linux内核有两种导出符号的方法给模块使用,一种方法是EXPORT_SYMBOL(),另外一种是EXPORT_SYMBOL_GPL()。这一点和模块A导出符号给模块B用是一致的。

内核的Documentation/DocBook/kernel-hacking(黑客).tmpl明确表明“the symbols exported by EXPORT_SYMBOL_GPL()can only be seen by modules with a MODULE_LICENSE()that specifies a GPL compatible license.”由此可见,内核用EXPORT_SYMBOL_GPL()导出的符号是不可以被非GPL模块引用的。

由于相当多的内核符号都是以EXPORT_SYMBOL_GPL()导出的,所以历史上曾经有一些公司把内核的EXPORT_SYMBOL_GPL()直接改为EXPORT_SYMBOL(),然后将修改后的内核以GPL形式发布。这样修改内核之后,模块不再使用内核的EXPORT_SYMBOL_GPL()符号,因此模块不再需要GPL。因此,这种做法可能构成“蓄意侵权(willful infringement)”。

另外一种做法是写一个wrapper内核模块(这个模块遵循GPL),把EXPORT_SYMBOL_GPL()导出的符号封装一次后再以EXPORT_SYMBOL()形式导出,而其他的模块不直接调用内核而是调用wrapper函数,如图所示。这种做法也具有争议。

实践
基于以上的基本原理我们可以进行一个测试,我们

先写一个简单的内核测试文件 内容如下


#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/gpio.h>
static int __init use_export_init(void)
{
    printk("USE EXPORT INIT \n");
    gpio_request(0,"GPIO0");
}

static void __exit use_export_exit(void)
{

}

module_init(use_export_init);
module_exit(use_export_exit);
MODULE_AUTHOR("YURI");
//自己定义一个非内核承认的协议,一般情况下就无法编译通过了
MODULE_LICENSE("YURI");


对这个测试文件进行编译就会发现编译不通过,报错如下:

FATAL: modpost: GPL-incompatible module use_export.ko uses GPL-only symbol ‘gpio_request’

非常明显gpio_request是被GPL导出的,直接用就意味着自己的代码也要申明为GPL,自己写代码倒是无所谓但是对于,商业用途是不合适的。

所以我又写了一个模块

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

int yuri_gpio_request(unsigned gpio, const char *label)
{
    return gpio_request(gpio, label);
}
EXPORT_SYMBOL(yuri_gpio_request);


static int __init export_init(void)
{
    return 0;
}

static void __exit export_exit(void)
{
}

module_init(export_init);
module_exit(export_exit);
MODULE_AUTHOR("YURI");
//作为使用内核的模块必须使用内核承认的协议
MODULE_LICENSE("GPL");


然后把之前的使用了gpio_request的模块修改成

#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/gpio.h>
#include "export.h"
static int __init use_export_init(void)
{
    printk("USE EXPORT INIT \n");
    yuri_gpio_request(0,"GPIO0");
}

static void __exit use_export_exit(void)
{

}

module_init(use_export_init);
module_exit(use_export_exit);
MODULE_AUTHOR("YURI");
//自己定义一个非内核承认的协议,一般情况下就无法编译通过了
MODULE_LICENSE("YURI");

这样以后 就可以避开GPL协议了。
————————————————
版权声明:本文为CSDN博主「与光同程」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/yy197696/article/details/126446314

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值