C编译器与C标准库的关系

3
我最近阅读了许多关于glibc函数如何在Linux中包装系统调用的内容。然而,我想知道glibc和GNU C编译器之间的关系。
举个例子,假设我想编写自己的C标准实现并编写一个名为“newglibc”的新库,稍微更改一些内容。例如,在系统调用之前和之后进行更多的检查和操作。我是否需要编写一个新的编译器?还是可以使用相同的GNU gcc编译器?

如果编译器完全与库分离,那么在理论上,如果有人能够将其转换为.exe并提供Windows提供的标准C库,他们是否能够在Windows系统上使用gcc?
谢谢

2
你可以使用相同的编译器。有一个开关“-nostdlib”可以关闭默认链接到glibc。已经有多个不同的标准库实现可用并在生产中使用。 - M.M
2
Glibc远不止是一个“标准C库”。正如您所提到的,它还处理“系统调用”,这些函数不属于C标准。此外,一些C标准库的部分不在glibc中,而在GCC特定的库中。 - Some programmer dude
2
你的第二个问题不太清楚,已经有gcc移植到Windows上了(这些移植并不使用glibc,因为glibc开发人员不希望支持Windows)。 - M.M
1
或者MinGW。还可能有其他的端口。 - Some programmer dude
我被告知用自己的实现替换RTL函数是UB。你肯定要小心,参见这个线程 - Paul Sanders
显示剩余2条评论
1个回答

5
Linux内核、GNU C库(“glibc”)和GNU编译器套件(gcc)是三个独立的开发项目。它们通常一起使用,但不必如此。名字中带有“GNU”的部分是GNU项目的正式组成部分,而Linux则不是。
C标准没有区分“编译器”和“库”;对于委员会来说,这都是同一个“实现”。 GCC与glibc是两个独立的开发项目,这在很大程度上是历史偶然性,但也是一种积极的选择:早期,每个商业Unix变体都附带了自己的C库和编译器,并且它们非常糟糕,典型情况下,90%的错误是由体积引起的。 GNU开始提供更好的编译器替代品(以及糟糕的shell工具)。
在传统的商业Unix上替换编译器比替换C库要容易得多,因为C库不仅仅是C标准第7条定义的函数;正如你所注意到的,它还提供了与内核最底层的接口,而且通常并没有很好地记录文档。 glibc曾经至少支持一些这些Unix系统,但现在它只能与Linux和一个实验性内核Hurd一起使用。相比之下,GCC支持几十个不同的CPU和内核,Linux支持数十个不同的CPU。
如果你编写自己的C库和/或内核,那么编写“后端”以便GCC可以生成跨编译器的代码相对容易,并且将GCC移植到该环境中运行略微困难一些。你可能还需要为汇编器和链接器编写后端,这是第四个项目(“GNU Binutils”)。将glibc移植到运行Linux的新CPU是一个庞大但简单的任务;将glibc移植到新操作系统是困难的,特别是如果该操作系统不像Unix一样。(Windows显然不像Unix,所以当微软想让在Windows下运行的Unix程序更容易时,最简单的方法就是将内部克隆的Linux内核添加到NT内核的侧面。我没有编造这个。)
如果你编写自己的C编译器,你将必须使其符合正在生成代码的库和内核的期望。其中很多已经在您工作的环境的“ABI”规范中记录下来了,但不幸的是并不全部都有。
如果以上内容仍不清楚,请告诉我们哪些地方需要澄清。

1
通常情况下,当你只是用newlibc替换GLIBC时(正如M.M在评论中已经指出的那样),根本不需要去碰GCC。 - Employed Russian
@EmployedRussian 如果你让你的newlibc看起来像GLIBC,当然可以。 - zwol
不需要使newlibc与GLIBC相似。GCC对所要编译和链接的libc几乎没有任何假设。 - Employed Russian
@EmployedRussian,那真的非常不准确。我不知道你是怎么得出这个印象的。 - zwol
你可能会感到非常困惑,但不管怎样。只需使用"-nostdinc"、"-nostartfiles"和"-nostdlib"即可与其他不同的newlibc链接。提供适当的newlibc组件,就可以完成了。不需要对GCC本身进行任何更改。 - Employed Russian
你可以从零开始尝试一下(使用-linux-gnu配置的gcc),并列出所有需要“newlibc”必须像glibc一样执行某些操作的地方,而这些操作不是由C、POSIX或ABI指定的。我向你保证,你会发现这个列表相当长。(我心中的这个列表中的大多数事项都与头文件的预期非标准内容有关,供参考。) - zwol

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接