Android:在争议中逃离Linux内核的GPL约束

2023-11-10

原文地址:http://tech.sina.com.cn/s/s/2012-05-28/09447177318.shtml

为这个题材起名,我思考了许久,GPL 是著名的开放源代码许可协议,Linux 内核开源项目正是在 GPL 的庇佑之下,十多年来在服务器、PC 端以及各种嵌入式设备上成绩斐然,是当之无愧的当代计算机软件的基石,说 GPL 代表着 Linux 的开源精神,毫不为过。然而,现实世界中,GPL 开源乌托邦和商业社会的丛林法则之间存在剧烈的冲突,其中犬牙交错,艰难成长,从中引发的思考,与大家共享。

  Linux 内核的 GPL 约束

  总所周知,Linux 内核以 GNU 通用公共许可证第二版(GPL V2)的授权使用协议下发行。GNU 通用公共许可证是一种 “Copyleft” 形式的“版权”,保障任何人都能够对 Linux 内核以及其衍生产品的使用、修改和重新发布的权力,前题是不能修改发布条款。什么意思呢,任何 Linux 内核的衍生产品(Derived Work)必须遵循 GPL 协议进行发布。然而问题的核心在于什么是 Linux 内核的衍生产品,其中有几个致命问题,业界争论了十年有多。

  1、使用 Linux 内核的头文件定义,进行系统调用的程序是否会被定性为衍生产品?

  2、链接使用了其他 GPL 的类库的程序是否会被定性为衍生产品?

  3、Linux 内核动态载入的模块 LKM(Loadable Kernel Modules)是否会被定性为衍生产品,以 LKM 形式开发的 Linux 驱动程序是不是衍生产品?

  如果上述问题答案均为“是”,GPL 将为 Linux 打造一个的“封闭” 的开源世界,什么意思呢?一个 Linux GPL的操作系统核心运行在 “ 内核空间 ” ,上层的类库、框架、服务、应用运行在 “ 用户空间 ” 。用户空间上的任何服务不可避免的需要Linux 内核的头文件,进行系统调用,因此,中间层服务必须遵循 GPL 进行开放源代码。调用中间服务层的框架或者其他服务使用了 GPL 的类库,因此,也必须是 GPL 的。同理,上层应用也被 “ 传染 ” ,必须是 GPL 的。于是,从内核到驱动到中间服务到上层应用,形成了一个 GPL 一体化软件授权的软件发布整体。可以认为,这个整体上任何开发成果都是 GPL 的,除非极少数的例外程序能够证明自身独立于系统的GPL环境。这样的一个“软件闭包”排斥的商业化的软件模块以及“想要钱”普通开发者,将整个软件世界划分为“ GPL 与 GPL 兼容的”的和非 GPL 的,每个开发从业者面临着选择,要么 Linux+GPL ,要么 Linux 与你无关。

  重新回到这三个问题,第一个问题,曾经被 Linux 内核的作者 Linus Torvalds 以及内核开发人员多次澄清普通系统调用为非 GPL 的作用范围,甚至固化在 Linux 内核的源码 COPYING 文档中,为 Linux 用户空间的程序采用非 GPL 的授权许可证打下了基础。

  第二个问题,具有明确的答案,是。这也是为何 GPL 被抨击为具有“病毒感染”的特性,一旦程序使用了 GPL 的模块,本身即被传染,程序必须成为 GPL。如果主程序与 GPL 类库是静态链接(Static Link)的关系,业界一般认为主程序必须限定为 GPL。而对主程序动态链接(Dynamic Link)GPL类库主程序一般认为也必须是GPL的,若要打赢官司,必须证明主程序与GPL模块之间具有“独立性和可区分性”(Separate and Independent),才能逃离 GPL 的约束。GPL 官方网站上的有这样的 FAQ:

  If a library is released under the GPL (not the LGPL), does that mean that any software which uses it has to be under the GPL or a GPL-compatible license? (#IfLibraryIsGPL)

  Yes, because the software as it is actually run includes the library。

  如果一个类库以 GPL 的许可证授权进行发布(不是 LGPL),是否意味着任何使用该类库的软件必须以 GPL 或者 GPL 兼容的许可证下进行发布?

  是,因为软件包含了该类库才能运作。

  第三个问题,是硬件厂商和 Linux 内核开发社区之间一场旷日持久的争论的中心。最著名的,莫过与图形显示设备厂商 AMD/ATI、NVidia 出自硬件规格保密以及知识产权的考虑,长期以二进制软件包的方式独立发布图形驱动,涉嫌违反了Linux内核开放源代码的软件授权协议 GPL,至今仍是 Unity 与 Gnome 3 等依赖于硬件图形加速的新型桌面技术发展上的一大阴影。主要的 Linux 内核维护者 Greg Kroah-Hartman 曾经严厉的批判过,内核中的二进制软件包发布的模块是非法的、不道德的。

  说到此处,可以看到 GPL 下的 Linux,存在着开源精神和商业机密以及知识产权保护相关的商业精神存在尖锐对立,对硬件厂商以及其他商业软件开发者来说,既不能忽视Linux广阔的商业市场,也不能放弃产品规格以及知识产权保护,两者都会伤害其立命之本。在早年的一份嵌入式操作系统选型的研究报告指出,Linux 相对于其他的 BSD 的 Unix Like 操作系统,由于 GPL 的约束限制,不具有商业优势。(参见引用3)。一言以蔽之,业界有 GPL 的恐惧症。

  然而,在移动互联网蓬勃发展的今天,一个 Linux 的发布版本,Android 在各种智能嵌入式设备上面大放异彩。据说,Android 之父 Andy Rubin 极度厌恶 GPL(James Bottomley,Linux SCSI 子系统的维护者说其人“Working from an extreme dislike of the GPL”),然而 Android 向世人展示了采用 GPL 授权代码的手机也能获得巨大的市场成功。

  Android:把 GPL 局限在内核空间

  下图是 Openfoundry 绘制的 Android 的授权许可证结构,可以看到在 Android 多层软件栈中,仅仅最核心的 Linux 内核使用了 GNU 通用公共许可证,在这个层次上,Google 对 Linux 内核的所有修改必须反馈回 Linux 主版本树(Android 的内核将在 Linux 3.3 版本进行回归,两个版本的 Linux 内核进行融合)。

  其上层的类库以及应用框架以及所谓用户空间部分,大部分使用了“ 温和 ”的 Apache-2.0 软件许可授权,允许 Android 上的开发商基于 Android 的源代码进行开发而不向社区反馈。基于上文讨论 GPL 的第一个问题,用户空间的类库以及程序使用 Linux 内核的系统调用不被视为是Linux内核的衍生产品,因而得以自由采用 Apache-2.0 的软件授权进行发布。GPL 世界和非GPL世界的分界线在于一个叫做 Bionic Libc 的类库。Bionic Libc 的关键之处在于如果 Bionic Libc 受到内核 GPL 的“感染”,将会波及非 GPL 的用户空间的各个模块。


Android的授权许可证结构

  Android 的 Bionic Libc 的类库,采用 BSD 的许可证授权。在 2008 年 Google IO大会上,一份著名的 PPT:“ Android Anatomy And Physiology ”讲到 Android 使用 Bionic Libc 类库替换Linux常用的 Gnu glibc ,其中一个主要原因是 “ We want to keep GPL out of user-space ”。(这其实有点难理解,毕竟 Gnu glibc 采用的是 LGPL 而非 GPL,并基于上文 GPL 第一点的讨论,使用系统调用的程序不再被视为 Linux 内核的衍生产品,并不需要遵循 GPL,有兴趣者请看下文用户空间驱动部分的分析) 。Bionic Libc 充满着非议,Bionic Libc 拷贝内核头文件的行为,并在源码中声明的版权信息均遭到了 “ 侵犯 Linux 内核 GPL 约束 ” 的质疑。这是 Bionic 头文件的版权信息,许多人认为是非法的:

  “This header was automatically generated from a Linux kernel header of the same name, to make information necessary for userspace to call into the kernel available to libc. It contains only constants, structures, and macros generated from the original header, and thus, contains no copyrightable information。”

  头文件由Linux内核的同名头文件自动生成,用来获取完成用户空间系统调用的必要的信息。它只包含原头文件中的常数、结构和宏定义,因此,不包含版权信息。

  不管如何,从目前的情况看,让 GPL 止步于内核空间的做法是成功的,并已经得到很大一部分内核开发者的认同。James Bottomley,Linux SCSI 子系统的维护者在 2011年 LinuxCon 大会日本站上谈到 Android 的商业成功与 GPL 恐惧的时候说:

  We should also design more “bright line” systems which make the question of GPL compliance clear. The kernel’s user-space ABI is one such system; developers know that user-space code is not considered to be derived from the kernel. Making the boundary easy to understand helps to make the GPL less scary。

  在遵守 GPL 的问题上,我们必须澄清一些界线。内核的用户空间 ABI(应用二进制接口)就是一种 GPL 的作用边界,能让开发者意识到用户空间的代码,不被定性为内核的衍生产品,如果 GPL 的界线清晰而易懂,可以帮助大家消除对 GPL 的恐惧。

  缓解 Linux 驱动的 GPL 困境

  Android 的发展离不开硬件设备厂商的支持,硬件设备厂商最关注的是 Linux 驱动的 GPL 约束问题,公开驱动程序源代码将会泄漏设备的硬件规格和泄漏核心知识产权,这是硬件厂商 GPL 恐惧的缘由。Google 不遗余力的为硬件设备厂家排忧艰难,保驾护航。上文提到的 “ Android Anatomy And Physiology ”,文中清晰的讲到 Android 在用户空间与内核空间之间存在着硬件抽象层 HAL(Hardware Abstraction Layer),HAL 类库本质上一种用户空间的驱动,其中的主要用途之一:规避GPL

  用户空间的驱动

  Linux 是单内核操作系统(Macrokernel),这种操作系统的一大特点是驱动存活在内核,优点是驱动与系统内核共生在相同的地址空间,运作的效率比较高,缺点是当驱动有问题的时候,容易危及内核的工作安全。用户区间驱动的思路是将驱动的主要业务逻辑剥离出来放到用户空间的主驱动模块中,内核中的驱动是个 “影子”驱动,只有透传控制命令和数据的功能。


规避GPL的机制

  Android 的 HAL 相当于上图中的主驱动,其在内核中的驱动相当于上图中的影子驱动。规避 GPL 的硬件厂家把需要保护的商业机密以及知识产权相关的逻辑放在 HAL 层,以二进制包的方式发布,不需要公开源代码。


规避GPL的机制

  这种机制看上去很美,然而,同样面临着巨大的争议。HAL 类库与内核驱动之间通过普通的系统调用能够完成么?如果不是普通的系统调用,用户空间的驱动就违反了上文中的第一条,用户空间的驱动不能获得 GPL 例外的豁免。Edward J. Naughton 2011 年 3 月撰文认为,普通的系统调用应被理解为 gnu glibc 向外暴露的系统调用接口,而 Android 通过 Bionic libc 类库暴露了更多的接口,包括原来在内核空间才能使用的接口,其目的是为了让用户空间的驱动能够充分的利用内核和硬件资源。如果情况果真如此,Bionic libc类库是 Google 的后门,这也可能 Android 抛弃使用 gnu glibc 重写 Bionic libc 的其中一个主要原因。Edward J. Naughton 说:

  Some of the calls exposed by Bionic are ordinarily not available to userspace because they’re excluded by the use of the #ifdef __KERNEL__ … #endif guards. If Google can define any call to the kernel from userspace as a “normal system call” (even those system calls ostensibly guarded by kernel matainers) simply by including it in its new C library, then a “normal system call” becomes whatever Google (or Oracle or Microsoft) wants it to be。

  Bionic 暴露了原来在用户空间不能使用的函数调用,这些调用原本在代码中被 __KERNEL__ 的宏定义保护其运行在内核状态。如果Google 只要将在 Bionic 添加暴露的接口就可以自由的暴露 Linux 系统调用(这些系统调用明显应该由 Linux 内核社区维护),那么难免被其他人效仿。

  总结

  总得说来,Android 为 GPL 下的 Linux 如何与商业社会并存与共赢提供了一个成功的范本,尝试为 Linux 生态系统上的各种角色划清彼此的作用范围,梳理了各方在版权上的权利和义务,目前看来获得了惊人的商业成功。然而,这种工作模式也面临着巨大的版权争议,理论上存在一种可能,一旦版权模式被否决,将面临被全盘否定的灾难。


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android:在争议中逃离Linux内核的GPL约束 的相关文章

  • Flutter - 每次应用程序重新启动后保留变量的值

    在我的一页上 我希望我的用户从一个变量上的默认文本开始 codeDialog 然后我希望他们更改该文本 之后他们编写的文本将成为我的新默认文本 遗憾的是我无法让它发挥作用 现在 当我重新启动应用程序并打开该屏幕时 它会重置为null 我认为
  • Android P Beta - AlarmManager 通知不起作用

    我正在 Android P beta 版本 4 上测试我的应用程序 我的应用程序目标SdkVersion是27 据观察 警报管理器通知未按预期工作 我使用下面的代码来设置通知 if android os Build VERSION SDK
  • 如何让Service即使被系统杀死也无法删除?

    我正在创建一个蓝光过滤器应用程序 因此 我想显示所有应用程序的视图 我通过以下服务做到了 public class OverlayService extends Service public OverlayService View mVie
  • 如何通过 Android 中的 Google Fit 集成获取用户信息

    我正在将 Google Fit 应用程序集成到 Android 应用程序中 以使用 SENSORS API 和 HISTORY API 跟踪健身数据 获取步数 如何使用该 API 获取用户信息 电子邮件或用户 ID 对你来说完美的例子 这可
  • 启动时的 Android pin 活动

    我有一个应用程序 它将自身注册为默认启动器 并在启动时自动固定自身 安装应用程序时这一切都正常 它会自行固定 并且只有后退按钮可见 问题是 当设备首次启动时 它无法正确固定 我多次看到一系列 屏幕固定 和 屏幕取消固定 的 toast 主页
  • 我该怎么办:这需要 android.permission.INTERACT_ACROSS_USERS_FULL

    我正在致力于将 micode 的开源指南针集成到我正在制作的应用程序中 我想知道当我在清单中以正确的拼写清楚地说明了此权限错误时 如何修复此权限错误 我仍然需要该许可 这让我很困惑 11 03 13 53 58 241 E AndroidR
  • 通过 id 查找 视图?

    如果视图是 id 是否可以通过 id 查找视图
  • 如何处理应用程序对 3d party 的依赖

    我当前正在开发的应用程序依赖于第三方应用程序 OIFileManager 我的问题是处理这些依赖关系的一般方法是什么 告诉用户解决它 嵌入 3d party apk 如果其许可证允许 自动解决 也许Android市场有相应的系统 没有自动的
  • Android 崩溃报告库(Froyo 之前)[重复]

    这个问题在这里已经有答案了 你知道 Android 的崩溃报告库吗 我不想花很多时间来编写自己的报告系统 输出可以发送到电子邮件或某种服务器 我知道 Google 在 Froyo 中引入了崩溃报告 但我想要一些适用于旧版本系统的东西 我们来
  • 如何在Android应用程序的同一屏幕上显示文本框的值,就像whatsapp一样

    这是我的主文件 我在其中调用按钮上的单击事件来传递值 protected void onCreate Bundle savedInstanceState super onCreate savedInstanceState setConten
  • CollapsingToolbarLayout 禁用绘制扩展

    我有一个已有条件禁用的 CollapsingToolbar 当用户在这种情况下加载视图时 它看起来就像一个普通的 ToolBar 对象 唯一奇怪的是 如果它们向下拖动 例如在拉动刷新样式操作中 折叠工具栏就会展开 尽管我的愿望和代码与此相反
  • 如何查看Android Asset资源?

    我想检查 assets 文件夹中是否存在文件 我怎样才能做到呢 请帮忙 我向我的应用程序类之一添加了一个辅助方法 我假设 应用程序运行时 资产列表不会更改 the List
  • android 从图库中选择图像

    我想从图库创建一个图片选择器 我使用代码 intent new Intent Intent ACTION PICK android provider MediaStore Images Media EXTERNAL CONTENT URI
  • 如何增加颤振中切屑的宽度

    我想增加宽度Chip 我怎样才能实现这个目标 Chip elevation 6 0 backgroundColor Colors white shape RoundedRectangleBorder borderRadius BorderR
  • ProGuard 与 Android:java.lang.NoSuchMethodError:android.util.Xml.asAttributeSet

    当 ProGuard 被禁用时 我的应用程序运行正常 启用ProGuard后 应用程序将导出为apk并安装到模拟器中 然后当我在模拟器中运行它时 强制关闭 05 10 11 14 10 582 E AndroidRuntime 759 FA
  • 有没有办法模拟小部件或屏幕特定位置的触摸?

    我想触摸或点击小部件上的某处 而不让用户在此时明确触摸屏幕 有什么办法可以做到吗 我已经检查了SO答案 有些人建议使用 集成测试 但在未物理或以某种方式连接到笔记本电脑的设备上无法执行 集成测试 无法找到更好的措辞 我还尝试进行 hitTe
  • Android 在通话期间播放音频文件[重复]

    这个问题在这里已经有答案了 对于我的 Android 应用程序 我想在从应用程序接听电话后播放音频文件 应用程序将发起电话呼叫 一旦接收者接听电话 应用程序应开始播放录制的音频文件 通过在谷歌上进行大量搜索 我发现这对于未root的设备来说
  • Windows 与 Linux 文本文件读取

    问题是 我最近从 Windows 切换到 Ubuntu 我的一些用于分析数据文件的 python 脚本给了我错误 我不确定如何正确解决 我当前仪器的数据文件输出如下 Header 有关仪器等的各种信息 Data 状态 代码 温度 字段等 0
  • 如何更改焦点/按下时图像按钮的色调

    我有一个ImageButton在我的应用程序中 当按钮打开时我需要更改图像的色调pressed focused 我有ImageButton设置为获取其src来自 XML 文件 如下所示
  • 使用 Android 的 Mobile Vision API 扫描二维码

    我跟着这个tutorial http code tutsplus com tutorials reading qr codes using the mobile vision api cms 24680关于如何构建可以扫描二维码的 Andr

随机推荐

  • java.lang.ClassCastException: java.math.BigDecimal cannot be cast to java.lang.Integer

    因为BigDecimal不能强制转换成 String类型 要用toString 作为中间桥梁转换 同理 Object BigDecimal转换成int doulbe long 也是一样的 List
  • 灰灰-判断是否存在重复数

    给定一个整数数组 判断是否存在重复元素 如果任何值在数组中出现至少两次 函数返回 true 如果数组中每个元素都不相同 则返回 false 示例 1 输入 1 2 3 1 输出 true 示例 2 输入 1 2 3 4 输出 false 示
  • QT笔记——QTableWidget 之 指定某列排序

    指定某列共有2种方式 1 重写 bool QTableWidgetItem operator lt const QTableWidgetItem other const 2 点击表头进行排序 connect ui tableWidget g
  • Python配置第三方库最全教程

    学Python最让人头疼的莫过于去配置一大堆杂乱的第三方库 而下载第三方库时报错也能让你崩溃 今天 我整理了一份全的教程 最常用的办法下载第三方库 在终端中执行 pip install 第三方库名称 大部分人一般不会报错 但偏偏我去安装最基
  • fbmem驱动框架分析

    文章目录 fbmem驱动框架分析 1 与misc驱动框架类比 1 1 my first cdev的记录 1 2 关于misc驱动框架的总结 2 fbmem驱动框架 2 1提供注册函数 2 2 操作函数分析 2 2 1 open函数分析 op
  • google analytics 添加跟踪代码

    google analytics添加跟踪代码实现统计分析 其代码添加方式共有三种 1 gtag js 基础代码
  • 个人网站搭建 04——WebHooks 实现远程项目的自动部署

    环境说明 Github 或 Gitee 维护的网站代码 支持 Webhooks 由于 Github 访问速度受限 易出现超时问题 我使用 Gitee 部署代码 Linux 公网服务器 阿里云 腾讯云 华为云等 服务器操作环境为 CentOS
  • Windows环境下 Redis RDB持久化无法生成dump.rdb文件

    Windows环境下 Redis RDB持久化无法生成dump rdb文件 问题 删除dump rdb文件 配置redis windows conf的SNAPSHOTTING 设置在60秒内进行了5次操作 即写入rdb文件中进行持久化保存
  • spring cloud 版本错Cannot resolve org.springframework.cloud:spring-cloud-starter-openfeign:unknown

    Cannot resolve org springframework cloud spring cloud starter openfeign unknown 说明 创建spring cloud项目后依赖错误 原因 版本错误 如下图 有些博
  • 怎么进入项目后台服务器,项目部署并常驻在服务器后台

    前言 上一次文章是自己的博客项目正式上线 这次分享 怎么让自己写好的项目常驻与服务器后台 在这之前 先了解一下服务器部署项目的一些环境依赖问题 服务器部署项目时 你的项目用到了什么环境 就要在服务器上安装相应的环境依赖 一般常要安装的就是M
  • 二进制颜色代码大全(含图)

    二进制颜色代码大全 可供大家开发时参考 FFFFFF DDDDDD AAAAAA 888888 666666 444444 000000 FFB7DD FF88C2 FF44AA FF0088 C10066 A20055 8C0044 FF
  • 如何证明凸函数的局部极小值为全局极小值

    最近上系统分析这门课的时候 老师提到了这个概念 当我们能够确定凸函数的局部最小值 这个最小值即为全局极小值 但并未给出证明 这里记录一下 主要用的还是凸函数的定义 凸函数区间任意位置的函数值小于两区间端点函数值之和
  • c#客户端Kafka的使用方法

    简介 Apache Kafka是一个分布式流处理平台 最初由LinkedIn开发 现在是Apache软件基金会的顶级项目之一 Kafka能够处理大规模的实时数据流 支持高可靠性 高可扩展性 低延迟和高吞吐量 它主要用于构建实时数据管道和流式
  • Pycharm debug 的使用

    Debug 作用的理解 若整个代码编写没有错误 且执行体没有设置断点时 Debug同正常运行模式 直接得到最终结果 当某一行代码设置断点后 在Debug模式下 代码会运行断点之前的所有程序 在断点处暂停 并在 变量窗口 可以查看所有主程序当
  • C#学习笔记:RadioButton控件与CheckBox控件的用法

    一 用途 1 RadioButton控件 单选按钮 当与其他单选按钮成对出现时 允许用户从一组选项中选择单个选项 也就是说 当同一个容器中 Form Panel GroupBox PictureBox等 存在两个以上的单选按钮时 只能有一个
  • C#对象和类--习题(1)

    1 一个景区根据游人的年龄收取不同价格的门票 请编写游人类 根据年龄段决定能够购买门票价格并输出 class XiTi string name int age void Xiti1 for 死循环 类似的while true Console
  • 代理模式——静态代理(贴近业务)

    静态代理概念 所谓静态也就是在程序运行前就已经存在代理类的字节码文件 代理类和委托类的关系在运行前就确定了 通常用于对原有业务逻辑的扩充 举例理解 以结婚为例 当事人只需要处理自己的主要事儿即可 比如典礼 洞房 其他的杂事儿可以交给代理公司
  • 乾坤实战教程

    一 什么是微前端架构 微前端不是单纯的前端框架或者工具 而是一套架构体系 这个概念最早在2016年底被提出 可以参考在Google上搜索Micro Frontends 排名靠前的http micro frontends org的博客文章 提
  • grpc arm 交叉编译(ubuntu 16.04)

    1 安装相关依赖工具 安装pkg config sudo apt get install pkg config 安装依赖文件 sudo apt get install autoconf automake libtool make g unz
  • Android:在争议中逃离Linux内核的GPL约束

    原文地址 http tech sina com cn s s 2012 05 28 09447177318 shtml 为这个题材起名 我思考了许久 GPL 是著名的开放源代码许可协议 Linux 内核开源项目正是在 GPL 的庇佑之下 十