编译器历史_编译器例程

编译器历史_编译器例程内核项目花费了很多精力来帮助使用旧的工具链的开发者。在一个新系统上编译内核本身已经是一个挑战了,如果还要被迫先安装一套指定版本的工具链的话就是一

编译器历史_编译器例程

内核项目花费了很多精力来帮助使用旧的工具链的开发者。在一个新系统上编译内核本身已经是一个挑战了,如果还要被迫先安装一套指定版本的工具链的话就是一个额外的负担了。因此,内核开发者们尽量保证大多数发行版中提供的工具链都可以成功编译内核。不过这个做法是有代价的,比如无法使用编译器里面的最新功能。并且,最近的一件事里看到,使用旧的编译器进行构建也会让开发者受到编译器中过去的 bug 的影响。

1 月 5 日,Russell King 报告了一个他调查了很久的问题。他有一些运行 5.4 或更高版本内核的 64 位 Arm 平台,极少数情况下会碰到 ext4 根文件系统校验失败。这个问题可能需要在正常测试中耗费长达三个月的时间才能复现一次,因此,正如 King 所描述的那样,“无法通过 bisect 二分法来调查是哪个补丁导致的问题”。不过,他后来找到了一种可以可靠重现的方法,这样一来就有可能确定出这个问题是何时引入的了。

在 King 报告这个问题之后,一些在 Arm 子系统中工作的开发人员研究了这个问题。他们花费了不少功夫之后指出这个提交是罪魁祸首。这个在 2019 年合并的改动,把 I/O 访问寄存器的函数中用到的内存分界线(memory barrier)操作进行了优化,提升了 I/O 内存的访问效率。撤销这个补丁后,问题就消失了。

通常开发人员会打上撤销补丁之后,宣称问题已经解决,但是这次不一样。这个问题补丁的作者 Will Deacon 坚信此补丁是正确无误的。如果 Arm 架构的行为是跟规范定义一致的,那么就不应该需要更多的内存分界线(memory barrier),所以他认为这个问题有个其他尚未查清的真正来源。换句话说,撤销补丁使问题消失了,但是它掩盖了其他地方的真正问题。

这个“别的地方”可能在哪里?King 认为,它可能在内核、Arm 处理器本身,或者是 相干互连(cache-coherent interconnect)(就是把 CPU 集群和内存连接起来的部分)。他认为硬件存在问题的可能性相对来说很小,因此这个错误应该是隐藏在内核的某个地方。这就引起了大量的代码检查工作,特别是在 ext4 文件系统内的代码检查。

两天后,King 宣布问题已经查清了,这的确是 ext4 文件系统内部的问题,但不是人们所预期的那种。仔细看ext4_chksum函数编译后生成的汇编代码,可以看到编译器会在函数本身结束前释放了函数的栈帧(stack frame )。该函数的最后一行是:

return *(u32 *)desc.ctx;

这里,desc是一个局部变量,存放在栈之中。编译后的函数会在读取desc.ctx之前重置栈指针到这个变量之上。这就导致了有那么一个瞬间(刚好可以执行一条指令)中,这个函数在使用已经被释放的栈区域。

这是一个最严重类型的编译器错误。错误编译出来的代码几乎每次都能正常完成任务,毕竟没有其他代码试图在这一个指令窗口中来分配堆栈空间。但是,如果恰好在两条指令之间发生了一次中断,那么问题就会出现了,栈会被覆盖掉,后来的 desc.ctx读取拿到的就会是个错误值,触发人们观察到的校验和失败错误。这几乎是永远不会发生的事情,但一旦发生,就会出大问题。

这个错误编译是由 2016 年 8 月发布的 GCC 4.9.4 产生的(4.9.0 是它所基于的主要版本,于 2014 年 4 月推出)。不过相关的 bug,在 2014 年就被报出来了,并在当年 11 月得到了修复。这个修复似乎从未从(当时的)开发分支也就是 5.x 版本分支反向移植回 4.9.x,所以 4.9.4 版本并不包含这个修复。有趣的是,像 Red Hat、Android 和 Linaro 这些发行版提供商所发布的 4.9.4 版本都有反向移植这个修复,所以它只影响了那些没有使用这些版本的开发者。这个 bug 在那里潜伏了好几年,直到最后出现在 King 的环境中。

这个事件在一方面清楚地展示了支持旧的工具链的潜在弊端。为了追踪一个事实上六年前就已经被修复的 bug,我们做了大量的工作。如果没有开发者还在使用 4.9.x 编译器的话,我们就不需要花费这个时间了。

恰好,GCC 4.9 是内核所支持的最老的编译器,但这也只是最近才公布的说法。直到 2018 年的时候,内核仍然宣称(不完全属实)可以使用 2002 年发布的 GCC 3.2 完成编译。2018 年的一些讨论之后,才将 GCC 最低版本提升到了 4.6,后来又变成了 4.9。

不可能再修复 GCC 4.9 来解决这个 bug 了,GCC 的开发者早就不在那个版本上工作了。所以,至少要把能用于编译 arm64 架构的编译器提升到 5.1 或以上了。但这马上就引出了一个问题,那就是是否应该将所有架构的编译器版本需求都提升上来。

Ted Ts’o 赞成这种改变,但他也指出,RHEL 7(包括衍生的 CentOS 7)系统仍然停留在 GCC 4.8 上。不过正如 Peter Zijlstra 所指出的,在这些系统上构建内核早就已经需要安装比发行版本身提供的编译器更新的版本了。Arnd Bergmann说,GCC 4.9 还有其他一些地方在用,比如 Android 和 Debian 8。Android 后来改用 Clang 来构建内核了,而 Debian 8 在 2020 年 6 月底就不再继续支持了。所以看来将 GCC 最低版本提高到 5.1,只会给很少用户带来不便。

另一方面,除了解决掉一个 bug 之外,这样的举动也有一些其他好处。Bergmann 认为这样做的话就可以允许用-std=gnu11来编译内核了,从而可能可以使用那些依赖C11的前沿特性。目前,内核编译使用的是-std=gnu89,也就是基于C89标准,不是那么亮眼。Zijlstra和Deacon都补充说,迁移到 5.1 就可以移除掉一些针对 GCC 4.9 上问题的临时措施了。

综上所述,似乎很少有人反对将内核整体转移到 GCC 5.1 或以上了。据说,Linus Torvalds 觉得这个改动的价值不是很明确,可能还需要一些更有说服力的信息。即使我们不会马上转向 GCC 5.1,但是 GCC 4.9 也不可能会有无限期的支持,这看起来是板上钉钉的事。当然,2015 年 4 月发布的 GCC 5.1 也不是什么新版本了。但我们希望它的隐藏 bug 少一些,同时也提供一些更受欢迎的新功能。支持老的工具链有它的价值,但有时候放弃最古老的工具链的做法也是有价值的。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
转载请注明出处: https://daima100.com/12009.html

(0)

相关推荐

  • Python 3格式化输出

    Python 3格式化输出Python是一种动态、面向对象、解释型和高级语言,因为其简单、易读、安全和可扩展等特点,越来越受到开发者的欢迎。Python中的输出功能非常强大,可以在控制台中显示从简单的字符串到复杂的数据结构。 Python提供了多种方法来格式化和输出这些信息,这些方法都经过精心设计,可以让程序员轻松地扩展代码。

    2024-06-02
    54
  • 大数据在车联网行业的实践与应用论文_车联网行业分析

    大数据在车联网行业的实践与应用论文_车联网行业分析**导读:**联友科技是一家旨在提供在汽车行业全价值链解决方案的科技公司。公司以数字化、智能零部件以及智能网联为三大核心业务领域,涵盖研发/制造/营销等领域的信息化产品、系统运行维护服务、云服务、大数

    2023-05-14
    149
  • Python中%的使用

    Python中%的使用在Python中,%是一种用于字符串格式化的操作符。它可以将不同类型的数据插入到字符串中的占位符中,生成一个新的字符串。%操作符支持的占位符有%s、%d、%f、%b等等,其中%s表示字符串,%d表示整数,%f表示浮点数,%b表示二进制数。

    2024-07-13
    41
  • 提高 Python 代码效率的实用技巧

    提高 Python 代码效率的实用技巧Python 是一种相对较慢的编程语言,但它非常流行并且有很多便于使用的库和工具。如果你正在使用 Python 编写大量的代码,那么如何提高代码的效率呢?在本文中,我们将从多个方面探讨 Python 代码的效率,并介绍一些实用技巧,以帮助大家更快地编写高效的 Python 代码。

    2023-12-06
    121
  • Windows Server 2008 R2远程使用win7 Aero主题

    Windows Server 2008 R2远程使用win7 Aero主题最近使用工作室服务器的时候,“厌倦了”系统默认的主题,所以开启了win7的Aero主题。因为服务器在阿里云买了之后,没怎么配置,所以有些功能需要先安装再使用。 打开“控制面板”选择“程序-打开或关闭Windows功能”,进入服务器管理器。 选择“角色-新建角色-服务器角色-远程…

    2023-11-10
    130
  • 使用MongoDB查询版本信息

    使用MongoDB查询版本信息a href=”https://beian.miit.gov.cn/”苏ICP备号-1/a Copyright www.python100.com .Some Rights Reserved.

    2024-08-30
    23
  • Python工程师教你如何正确使用os.path.join进行路径拼接

    Python工程师教你如何正确使用os.path.join进行路径拼接在Python中,文件操作是经常要用到的,而路径操作则是文件操作中重要的一部分。本篇文章将从多个方面介绍如何正确使用os.path.join进行路径拼接。

    2024-04-16
    75
  • 周岁、虚岁、实岁

    周岁、虚岁、实岁文章浏览阅读1k次。有人说,在全世界,或许只有中国人有两个年龄,一个周岁,一个虚岁。虚岁是中国的传统概念,所以是以农历年份来划分的。虚岁(又叫毛岁):出生时为一岁,每到春节长一岁。周岁:出生时为零岁,每到公历生日(不是生日第二天)长一岁。还

    2023-11-08
    125

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注