精子最近在开发一个「简单」的容器平台 DeployBeta,目前还在非常早期的阶段。

自由软件和开源许可证

本文整理自 彩排 中的一期播客。

什么是自由软件

我总结了三点自由:

  • 出于任何目的、以任何方式 使用该软件的自由(包括商业用途,一些商业软件限制你不得进行破解、不能用于犯罪活动就是在限制你使用的方式或目的)。
  • 修改软件的自由,当然修改软件的前提是你要能够得到源代码。
  • 重新分发的自由,不仅是分发原始版本,你也可以分发修改后的版本。

只有符合这三条才可以算自由软件,有一些只开源代码(可能是为了安全审计,或者只限非商业用途)的软件并不能算自由软件。

我们经常看到的 GPL、Apache、MIT 都属于自由软件许可证,这些许可证会在前面的三项自由之外附加一些限制条款,但这些限制条款与自由软件中的自由并不冲突。

Copyleft 的 GPL 家族

在自由软件许可证中,有一类特殊的被称为 Copyleft 的许可证(Copyleft 是一个与 Copyright 相对的词,代表着一种具有「传染性」的自由),其中最知名的就是 GPL 家族了,我们接下来会聊到其中的 GPL、LGPL 和 AGPL。

Copyleft 的特点在于它有一种理想主义的野心 —— 它希望这个世界上所有的软件都是自由的,因此这些许可证都是具有「传染性」的。它们在自由软件的基础上附加了一个最主要的限制条款:在重新分发 Copyleft 的软件时,必须授予用户同等的自由、也必须附加同等的限制条款。在实践中一般就是说,你修改一个 GPL 的软件后,你再发布的时候也必须是 GPL,其他人修改了你修改后的软件,也必须是 GPL,这就是所谓的传染性。

自由软件社区中有很多使用 GPL 许可证的软件,例如我们熟知的 Linux、WordPress 等等。说到 WordPress,现在有很多公开出售 WordPress 主题或插件的社区,但按照 GPL 的许可证,主题或插件中的 PHP 代码显然属于衍生作品,必须使用 GPL 许可证来发布(而 CSS 和 JavaScript 可以通过单独以其他协议发布来规避),所以理论上,任何一个人购买了 WordPress 主题,那么他都可以随意地再次出售这个主题(这是 GPL 授予他的权利),在 2013 年我便就此话题写过一篇 文章

GPL 中的衍生作品

我们再来看 GPL 的限制条款,即「再分发衍生作品时必须授予用户同等的自由」,这里有两个词可以单独拿出来讨论一下,「分发」和「衍生作品」。

所谓 分发 就是说你把这个软件(包括修改后的版本)发送给其他人使用,例如你开发了一个桌面软件,当你给用户提供下载时,这就是一种分发行为;当你提供一个库(无论是源代码还是二进制版本)也是一次分发行为;甚至包括浏览器中的 JavaScript 也算分发行为 —— 因为用户的浏览器需要从你的服务器下载 JavaScript.

GPL 为了保证用户有修改软件的自由,要求你在进行分发时同时提供源代码。而分发可能是公开的,也可能是小范围的,如果你在网络上公开发布一个软件,那么你也必须公开发布源代码;但如果你只是私下发给一个朋友,或在公司内部分发一个内部软件,那么你只需要向这个朋友,或者在你的公司内部提供源代码。所以说「分发」和「提供源代码」的行为是挂钩的,你向谁分发就向谁提供源代码。

所谓 衍生作品,GPL 认为只要你的项目中用到了 GPL 的代码,都可以算衍生代码,无论你是把 GPL 代码作为一个主要功能,还是用来做一个非常细枝末节的功能。而且 GPL 感染的对象是你的整个软件,也就是说只要你的项目用了 GPL,那么整个项目都被感染成了 GPL,你在进行发布时需要提供整个项目的源代码。

这样听起来 GPL 的确很流氓,那么具体到条款上,GPL 什么情况下会感染你的项目呢?我总结了一下,除非你采用以下三种隔离方法中的一种,将 GPL 代码与你的项目进行了隔离,都在都会被 GPL 感染:

  • 内存地址空间隔离,即如果你的代码和用到的 GPL 代码不共享内存地址空间,例如分别属于两个进程(操作系统帮你做了内存地址空间隔离),或者分别属于内核态和用户态那么就不算衍生作品,例如 Linux 并不会感染运行在 Linux 上的程序。
  • 代码和数据隔离,即如果你的代码和 GPL 的代码是分别作为代码和数据被看待的,那么不算衍生作品。例如用 GCC 编译你的程序是不会感染的,因为在编译时,你的程序是作为数据被看待的;同理,用 Emacs 编写代码也不会感染被编写的代码。
  • 指令计数器隔离,这个是针对虚拟机的一种例外,像 JVM 这样的运行环境,实际上是虚拟了一个 CPU 去执行其上的 Java 操作码,这个虚拟的 CPU 实际上有着和物理 CPU 不同的指令计数器(即 CPU 用来记录当前执行位置的寄存器),因此 JVM 不会感染运行在其上的 Java 代码。

注意这里的例外并不包括静态链接和动态链接,因此如果你静态链接一个 GPL 的库也是会感染你的整个项目的;至于动态链接则目前还存在争议,GNU 极力认为动态链接也在感染的范围内。

LGPL

除了 GPL 还有一个叫 LGPL 的许可证,它是一个比 GPL 宽松一些的许可证,LGPL 中将衍生作品的范围减少到「同一个编译单元」,允许用户在使用了 LGPL 的静态链接库时,仅将 LGPL 代码所属的编译单元开源,所谓编译单元在 C 这样的语言里就是一个文件,若干个编译单元会在最后被链接到一起,形成一个可执行文件。

但如果推广到一些并没有明确区分编译和链接环节的基于虚拟机的语言(例如 Java 或 JavaScript)中,则还有一些争议,一般是认为一个包属于一个编译单元。

LGPL 被广泛地使用在依赖库中,例如 Qt 和 FFmpeg 都使用 LGPL 许可证,但实际上作为 GNU 之父的 Richard 后来并不建议大家使用 LGPL,而是建议大家直接使用原版的 GPL。

他在一篇题为「Why you shouldn’t use LGPL for your next library」的文章中说,非自由软件的开发者往往都有很多金钱上的优势,我们这些自由软件的开发者必须团结起来以便得到某种优势来和他们对抗。如果我们发布的库都使用原版的 GPL,那么我们这些自由软件开发者将获得一种巨大的优势 —— 我们可以使用这些库,但那些非自由软件开发者却不能。

所以后来 Richard 将 LGPL 的全称从 GNU Library License 改为了 GNU Lesser License,并且不建议大家在新的项目中使用。

GPL 在法律上的现状

GPL 在法律上的现状并不乐观,很多时候 GPL 是一种君子协定,很多人经常是基于道德,或者很多公司是基于声誉的考量才去遵守 GPL。虽然 GPL 许可证本质上是一种合同,将代码的使用权有限制地授予愿意遵守这个限制的人。但 GPL 的主要诉求是「开源代码」,而即使赢得诉讼,(至少在中国)法院也不会帮你强制执行「开源代码」这一判决;因为通常法院只能强制执行经济类的判决,如果你要求经济上的赔偿的话,因为 GPL 中并没有写明不遵守许可证的情况下的罚金,因此你可能需要证明被告不开源这一行为给他带来了多大的利益或者给你造成了多大损失,注意并不是他使用你的代码得到的利益,而仅仅是不开源这一行为的利益。

尤其很多开源项目并没有精力去打官司,一部分开源软件可能只是会在网站上登出一个「耻辱柱」的页面,列出哪些项目或公司使用了他们的代码却没有遵守 GPL 许可证,例如 FFmpeg 的网站

AGPL

接下来我们来介绍 GPL 家族的另一位成员 AGPL,AGPL 是一个更严格的 GPL 协议,代表性的项目是 MongoDB —— 一个非常知名的非关系型数据库。考虑到现在是互联网时代,很多公司会将 MongoDB 之类的开源软件进行一些修改或封装,然后提供基于 MongoDB 的云服务来盈利。于是就有了 AGPL 许可证,AGPL 将分发的行为扩展到了「通过网络提供服务」,之前的 GPL 对于服务器端应用是没有什么约束的,因为服务器端应用并不会发布给最终用户,但如果你使用了 AGPL 来通过网络提供服务,那么你也需要开源你对其的修改。

就在发文前,MongoDB 宣布新版本将会切换到 SSPL,这个协议是对 AGPL 的进一步细化,规定了若提供主要价值来自于 MongoDB 的云服务,就必须开源能够让用户运行起来这个服务所需的所有组件,包括用户界面、API、自动化、监控、备份等组件。

非 Copyleft 许可证

前面花了很多篇幅去介绍 GPL 家族,的确他们是自由软件中最有趣也最优代表性的部分。但现在一些新的开源软件往往会选择一个非 Copyleft 的许可证,例如 Apache、BSD、MIT 等等,不过这些协议的条款相对简单,一句话便可概括。

其中 MIT 许可证仅仅要求用户进行署名,所谓署名是你必须将用到的自由软件代码的许可证附带在你分发的每份软件中,并且让用户能够看到,例如在很多软件的某个隐蔽的角落,你可以看到一个叫「开源许可证」或「法律信息」的按钮,点开可以看到它用到的所有自由软件的许可证。

当然你也就可以连署名都不要求的话,你可以选择直接将你的作品释放到共有领域,例如 SQLite(一个嵌入式关系型数据库)就直接被发布到了共有领域,你可以用它的代码做任何事情,连署名都不需要。

BSD 会稍微严格一些,除了要求署名之外还要求用户不得使用其名字用作宣传的用途,例如你基于一个 BSD 协议的软件发布了一个修改后的版本你必须为它起一个新的名字,和原有项目做出明确的区分,以免误导其他用户。

而 Apache 许可证在 BSD 的基础上还要求你在发布修改后的版本时明确注明对哪些文件、做了什么修改。

这里需要注意的一点是这些许可证的授权往往是 不可撤销 的,一旦你曾经以某个许可证发布了一个项目,那么任何人都可以按照你当时发布的那个版本的许可证去使用你当时发布的那个版本的代码。当然你可以从某个时间点开始以新的许可证来发布代码,但其他人依然可以选择遵守旧的许可证去使用旧的版本。这一点是写在大部分自由软件许可证中的条款,是出于保护自由软件代码的使用者的考虑,否认如果你可以随时收回你的授权,是没有任何人敢去用你的代码的。

Creative Commons

前面我们提到的的都是针对于代码的许可证,但有的时候我们也希望授予文本作品的读者一些自由。我接下来介绍的这个「创作共用许可证」就是这样的一种许可证,通常缩写为 CC.

CC 许可证将文本作品的作者常见的几种诉求总结成了四点:

  • BY 署名
  • SA 相同方式共享,所有的衍生作品都必须使用同样的许可证,类似于 GPL 的要求,但因为文本作品的衍生关系相对简单,所以可能并没有太多人关注它的传染性
  • NC 禁止商业使用
  • ND 禁止演绎

这四种诉求可以被组合到一起,例如我的博客选用了 CC 署名、非商业使用、相同方式共享发布。也就是说你可以非商业的目的自由地使用和分发这篇文章,需要提供指向 caipai.fm 的链接,如果你修改了文章则必须也允许其他人以相同的方式转载和修改。

CLA

我们还会看到一些软件同时是自由软件(比如 Qt 和 MySQL),也提供了商业授权,如果你购买了他们的商业授权,那么你并不需要遵守自由软件的许可证,这是如何做到的呢?

首先,一个作品的作者是有权决定如何把这个作品的使用权授予其他人的,他可以即发布一个面向所有人的自由软件许可证的版本,当然这个自由软件版本其实也是有限制的;他也可以以单独的、有着完全不同的限制的方式来把使用权授予其他人,商业授权就是这样实现的。

但很多社区开发的自由软件,例如 Linux,一旦有来自社区的贡献者参与了进来之后,最初的发起者就没有权利去修改许可证或发行商业版本了,因为这时已经没有人拥有这个软件的所有的代码的所有权利了,因为这个软件的不同的部分的代码来自不同的贡献者,他们只是以这个项目的自由软件许可证发布他们的代码,所有人都必须遵守这个自由软件许可证,而显然将一个 GPL 许可证的自由软件改为其他非 Copyleft 许可证是不行的,因为这违反了 GPL 许可证的要求。

所以在实践上,很多社区开发的软件会要求贡献者在提交代码之前签署一份协议(通常缩写为 CLA),这份协议的主要内容有两点:

  • 贡献者授予软件的维护者有关此次贡献的代码的永久的、无限制的使用权(而不仅仅是按照自由软件许可证授权)。
  • 贡献者声明自己拥有所贡献的代码的相关权利(而不是从另外一个不兼容的许可证的项目、或非开源项目中拷贝的)。

如果一个社区开发的软件一开始就这么做,那么第一条保证了软件的维护者始终拥有对所有代码的没有限制的使用权,这样项目的维护者才有可能修改许可证或者发行商业授权;而第二点我个人认为只是为了在出现著作权纠纷时,规避一些法律上的问题。

拓展阅读:

入手 Tenda Nova MW6(Mesh 路由器)

我之前在用的路由器是 Synology 的 RT1900ac,当时非常粉 Synology,于是也想试试他们家的路由器。但现在看来这绝对不是一个正确的选择 —— 我既然已经有了 Synology 的 NAS,他们家的路由器上的很多功能对我来说就显得重复了。

Mesh Wi-Fi

RT1900ac 的信号覆盖也并不理想 —— 我仔细想了一下,信号强度不仅仅在于路由器的发射强度,因为接入设备(例如手机)也是要将信号回传给路由器的,有可能回传才是瓶颈。因此,更好的做法是提高路由器(AP)的密度,缩短和接入设备之间的距离。

于是,我发现了 Mesh Wi-Fi 这项技术,也称作「分布式路由器」、「网状网络」、「多跳网络」,对应 IEEE 的 802.11s 标准。简单来说就是一个网络由多个节点(例如 3 个路由器)构成,任意两个节点之间都通过无线(Wi-Fi)或有线(所谓「有线回程」功能)连接。这些节点提供相同的 SSID,设备会接入最近的节点,网络流量可能会经过多个节点之间的传递,最后到达外网网关(接宽带猫的节点)。与桥接网络相比,在多个节点之间可以无缝漫游(IEEE 802.11v/r)。

2018/nova-mw6-mesh.png

这样的技术解决了前面提到的问题,即提高路由器的密度、提高信号覆盖、缩短接入设备和路由器之间的距离。一开始我是想买 UBNT 的 AmpliFi,可实在太贵了。于是我最后买了 Tenda Nova MW6(3 个节点),大概是 Amplifi 三分之一的价格,算是 Mesh Wi-Fi 解决方案里价格较低的了,其实 Tenda 还有更便宜的 Mesh Wi-Fi,不过是百兆的。

信号覆盖

为了量化信号覆盖的改善效果,我在切换路由器前先测量了 RT1900ac 的信号覆盖情况(5G 信号):

2018/nova-mw6-rt1900ac-snr.png

图中的数字是信噪比,越高表示信号越好。可以看到之前的 RT1900ac 因为放在客厅,在卧室中的信号是非常差的。接下来再看一下 Nova MW6 的信号覆盖情况(5G 信号):

2018/nova-mw6-snr.png

我实际上是部署了 3 个节点的,但似乎 NetSpot 只识别出了其中 2 个节点。可以看到因为卧室也有一个节点,所以卧室的信噪比从之前最低的 15% 提高了现在的最低 57%。

带宽测试

外网表现上,是可以跑满运营商宽带 85Mbps 的下行和 3Mbps 的上行的:

2018/nova-mw6-speedtest.png

内网表现上,我分别测试了很多情况,需要注意的是受到我手里设备类型的限制,这些测试并没有充分地控制变量:

  • 设备 有线连接 到不同的节点,节点之间无线连接:300Mbps
  • 设备 无线连接(5G)到 不同 的节点,节点之间无线连接:200Mbps
  • 设备 无线连接(5G)到 相同 的节点,节点之间无线连接:200Mbps

关于运营商

从四月末从北京搬到昆山以来,在昆山办理的联通宽带的质量非常差,下行跑不到标称的 100Mbps 不说,上行在绝大部分时间只有 2Mbps,而且一旦跑满 2Mbps 就会「断网」一段时间。

之前的 RT1900ac 在这种异常的「断网」之后不会自动重连,每次都需要登录路由器管理界面手动重播 PPPoE,这也是这次换路由器的原因之一,新的路由器在这种情况下会自动恢复,但断网的现象依旧存在。

如果要是我之前一个人的话,估计会嫌麻烦凑合用下去,但在蛋黄的反复报修、投诉下 —— 问题依然没有解决,只不过了解了更多的内情。联通的宽带安装人员表示我们小区靠南的几栋楼容量不足,本不应该允许办理 100Mbps 的宽带,如今必须扩容才能彻底解决这个容量问题,并表示会帮助我向上级反映。

使用体验

Tenda Nova MW6 被设计成只能通过手机应用来进行配置,而且配置界面非常简单,不能设置频段、不能单独开关 2.4G 网络、不能看到路由器的负载情况(CPU)。不过这也意味着没有乱七八糟的广告植入和强迫用户使用的功能,至少目前是这样

设置界面中有一个「智能 QoS」的功能,按我的理解,这这里设置宽带的上下行带宽之后,路由器应该在带宽快要被用满时限制占用带宽(对于我来说主要是上行)过多的设备。但实际表现上并不理想,依然经常出现上行带宽被占满,导致下行也无速度的情况,不过我并不确定这是路由器 QoS 不起作用,还是运营商在带宽快要被用满时的特殊行为。

而且在固件升级的过程中遇到了一些问题,一开始我在只启动了一个节点的情况下进行了固件升级。之后连上其他 2 个节点后,就无法对剩余两个节点进行固件升级了,最后我不得不重置了所有的节点,然后单独对剩余的两个节点进行升级。

关于无缝漫游,在实际使用中确实 Wi-Fi 信号总是满格,不会出现桥接网络时在两个路由器中间时信号较差的情况。我在整个屋子移动的过程中一直开着 ping 发现在切换节点时会出现一秒钟的延迟较高(从 50ms 增加到 200ms)的现象,但因为缺乏使用场景,我并不是很清楚对于更上层的应用(例如游戏),节点会有什么影响,反正如果只是刷刷网页、看看视频,这个效果应该足够了。

理论上既然是分布式 Wi-Fi,单个节点失效不应该影响其他节点(官方的介绍上也是这么说的),但我实测发现接入外网网关的节点实际上是「主节点」,一旦主节点关机,整个网络都会失效(无法搜索到 SSID),无法进行内网通讯。

游戏:城市天际线(Cities: Skylines)

欢迎关注 我的 Steam 帐号,截至本文发布时的总游戏时间为 186 小时

因为 SimCity 2013 的失利,2015 年发售的城市天际线可以说是目前最好的城市建造类游戏了,三年以来也保持着稳定的更新(虽然每个 DLC 的价格都和游戏本体差不多了),相比于 SimCity 2013, 天际线没有无趣的「城市间交互」,取而代之的是更大的地图。

2018/skylines-overview.png

天际线的经营要素并不是很强,只要前期不作死 —— 不规划远超实际需要的基础设施,就不太可能出现破产的情况,从中后期开始主要的重心还是在交通上面。当然不同的人在玩这个游戏时会有不同的目标,我的目标是在不使用 Mod 的情况下、在默认的游戏规则下,建造一个看上去符合「常理」、运转起来也符合「常理」的城市。

2018/skylines-budget.png

天际线在一些方面提供了非常细致的模拟,例如有对市民的人生阶段的模拟:先上小学、再上中学、再上大学或开始工作,最后退休在家;也有对于每个市民的住所、学校或工作地点和通勤路线的模拟,市民会在步行、公共交通、私家车之间换乘;对于工业区也会模拟每个工厂进货(进口或来自其他工厂)和出货(出口或去往本地工厂、商店)的交通路径;不同的工作对于市民的教育程度有不同的要求;治安、消防、垃圾等市政服务的覆盖范围是取决于交通状况的。

在道路建设的方面,天际线提供了很大的自由度,所有的道路都可以提升为桥梁或下沉为隧道,自带的曲线工具和对齐工具可以帮助你建造出完美的道路和立交桥,但游戏也在桥梁的跨度、角度、坡度方面进行了一定的限制,不允许建造不符合常理的道路。游戏提供了三种等级(分别为 2、4、6 条车道)的城市道路,和几种不同样式的高速道路,车辆会更偏好选择高等级的道路来行驶,这样你便可以通过建造不同等级的道路来引导车流。游戏也提供了单行线、人行道(可提升为天桥或下沉为隧道)、非对称数量车道、公交专用道等各种不同类型的道路以供选用。

2018/skylines-overpass.png

游戏中后期的主要内容就是解决交通拥堵了,游戏中的车流主要集中在商业区和工业区,而居民区的交通需求大部分可以用公共交通替代。工业区因为本身有污染、重型卡车比较多,在规划上会和其他区域分离,直接接入高速道路。高速道路负责区域间的长距离交通,和城市道路的互通都要靠无信号灯、车流交叉较少的立交来实现,保证高速道路不会出现拥堵;当然也会有一些级别稍低的高速路,出于占地的考量,是会出现和城市道路的路口的。在城市道路中,通过分级的路网来控制车流,在高等级道路上使用较高的路口间距,在低等级道路上不再设置信号灯等等。

参考链接:交通规划指南

在最近的一个交通 DLC 之后,已经可以为道路设置「主干道」属性,也可以单独控制每个路口有无信号灯了。但我仍对默认的交通系统有些怨念,比如不能为路口设置禁止左转 —— 通常一条小路汇入主干道时是禁止左转的;游戏中的信号灯对于直行和左转是同时放行的;车辆的车道变换也显得非常不自然。

2018/skylines-crossing.png

在公共交通方面,天际线提供了公交、电车、地铁、轻轨、铁路、轮渡、飞机、飞艇、缆车、出租车,不过在我的实际使用中觉得很多交通工具提供的能力是重复的,城市内交通只要公交和地铁就可以了,城际交通(游客)靠飞机和铁路,货运靠铁路和货运港口。游戏中公交和地铁的线路和站点都是要自己规划的(也可以调整每条线路配置的车辆数量),并不像 SimCity 那样只要放置车站就可以了。这个设计带来了很多可玩性,设计得好的公共交通系统和设计得不好的交通系统将会有非常大的差别,你需要观察已有线路的客流数据(每个站点的客流量和等待人数)去进行调整、规划新的线路。

2018/skylines-mass-traffic.png

我对公共交通的怨念主要在于我认为地铁和轻轨其实是完全一样的,为何不直接让地铁可以提升到陆地或高架呢?以及游戏默认没有提供地铁的换乘车站,所以要么站外换乘,要么多个线路共用一个站台(会非常堵);以及目前游戏中不同公共交通的换乘还比较弱,火车总站和公交总站规模过大,没有中等规模的车站。

天际线默认提供了 36 平方公里的地图,使用 Mod 可以扩大到 300 平方公里以上,几乎相当于一个真正的城市了。对于这么大的地图,游戏也提供了丰富的管理工具,你可以为每个建筑、道路、公共交通线路、甚至市民命名,也可以划分行政区,在不同的行政区使用不同的政策和税率。

2018/skylines-map-view.png

图中的城市是我近期耗时几十个小时建造的一个城市,目前有人口 16 万人(相比于城市规模,天际线的人口数量不是很真实,严重偏少)。

12374

精子生于 1995.11.25, 21 岁,英文 ID jysperm.

订阅推送

通过邮件订阅精子的博客日志、产品和项目的最新动态,精子承诺每一封邮件都会认真撰写(历史邮件),有想和精子说的话也可以直接回复邮件。

该博客使用基于  Hexo  的  simpleblock  主题。博客内容使用  CC BY-NC-SA 3.0  授权发布。最后生成于 2018-10-22.