Linux内核如何进行自身编译?


88

在计算机上安装Linux系统时,我不太了解Linux内核的编译过程。

以下是使我感到困惑的一些事情:

  1. 内核是用C编写的,但是如何在不安装编译器的情况下编译内核?
  2. 如果在编译内核之前在我的机器上安装了C编译器,那么在没有安装编译器的情况下如何编译该编译器本身?

几天来我都很困惑,感谢您的回复。


据了解,C编译器是由AT&T实验室的一些疯狂而聪明的人用某种解释器编写的,用于为给定计算机编译UNIX(请注意,历史始于UNIX,而不是linux,所以恐怕您错过一章...或其中的几个!)。简短的故事是,无需为不同的计算机重写unix内核,只要这些计算机具有适用于C语言的适当编译器即可。这些编译器是用目标计算机的特定编译器编写的。奋力说“首先用给定计算机的编写程序编写编译器,然后用C用UNIX编写”
Victor

Answers:


208

Linux盒的第一轮二进制文件建立在其他Linux盒上(可能)。

第一个Linux系统的二进制文件是在其他平台上构建的。

该计算机的二进制文件可以将其根源追溯到在另一个平台上构建的原始系统。

...

进行足够的深入研究,您会发现使用更多原始工具构建的编译器,这些工具又是在主机以外的机器上构建的。

...

继续推动,您会发现内置的计算机可以通过设置机器前面板上的开关来输入其说明。

很酷的东西。

规则是“构建工具以构建工具以构建工具...”。非常类似于运行我们的物理环境的工具。也称为“自举”。


3
不一定是不干净的。只是未优化。将优先选择第一个编译器以在386上工作,但对于任何体系结构,都会重新编译版本。
布列塔尼

1
您可以添加第三阶段,如果一切正常,则第二阶段的输出应等于第三阶段的输出。
伊斯梅尔

27
不仅仅是软件,还有硬件。没有计算机就无法构建P4(甚至486)之类的东西。
BCS

1
@BCS:哦,是的。我们已经达到了软件和硬件工具深深地相互联系和相互依存的地步。
dmckee ---前主持人小猫,

4
“一个有效的复杂系统总是被发现是从一个有效的简单系统演变而来的。” en.wikipedia.org/wiki/Gall's_law
ajuc

33

我认为您应该区分:

compile v:使用编译器处理源代码并生成可执行代码[1]

install,v:连接,设置或准备使用的东西[2]

编译从源代码生成二进制可执行文件。安装只是将这些二进制可执行文件放在正确的位置,以便以后运行它们。因此,如果二进制文件可用,则安装和使用不需要编译。分别考虑“编译”和“安装”,例如“烹饪”和“服务”。

现在,您的问题是:

  1. 内核是用C编写的,但是如何在不安装编译器的情况下编译内核?

没有编译器就无法编译内核,但是可以从编译后的二进制文件安装内核。

通常,当您安装操作系统时,会安装一个预编译的内核(二进制可执行文件)。它是由其他人编译的。而且,仅当您要自己编译内核时,才需要源代码,编译器以及所有其他工具。

即使在像gentoo这样的“基于源”的发行版中,您也将从运行已编译的二进制文件开始。

因此,您可以一生不编译内核,因为您可以由其他人编译内核。

  1. 如果在编译内核之前在我的机器上安装了C编译器,那么在没有安装编译器的情况下如何编译该编译器本身?

如果没有内核(OS),则无法运行编译器。因此,必须安装一个已编译的内核来运行编译器,但不需要自己编译内核。

同样,最常见的做法是安装编译器的已编译二进制文件,并使用它们来编译其他任何文件(包括编译器本身和内核)。

现在,鸡肉和鸡蛋的问题。第一个二进制文件是由其他人编译的... dmckee给出了一个很好的答案。


14

描述此现象的术语是自举,是一个有趣的概念。如果您考虑嵌入式开发,那么很明显,许多需要软件的设备(例如闹钟,微波炉,遥控器)的功能不足以编译自己的软件。实际上,这类设备通常没有足够的资源来远程运行像编译器这样的复杂操作。

他们的软件是在台式机上开发的,一旦编译就可以复制。

如果您对这种事情感兴趣,那么我脑海中浮现的一篇文章是:关于信任信任的思考pdf),这是一本经典且有趣的文章。


1
您将交叉编译与引导混淆在一起。第一个涉及仅在PC上存在的编译器,该编译器为目标体系结构创建操作码。显然,没有其他计算机就无法做到这一点,因此存在鸡与蛋的困境。困境的答案是引导程序,即使用手写或预先存在的简单编译器生成更复杂的编译器。
凯文·维米尔

12

内核不会自行编译,而是由C编译器在用户空间中编译的。在大多数CPU架构中,CPU在特殊寄存器中具有许多位,这些位代表当前运行的代码具有哪些特权。在x86中,这些是代码段(CS)寄存器中的当前特权级别位(CPL)。如果CPL位为00,则表示代码在安全环0(也称为内核模式)中运行。如果CPL位为11,则表示该代码在安全环3(也称为用户模式)中运行。很少使用其他两个组合01和10(分别是安全环1和2)。

关于在用户模式和内核模式下哪些代码可以执行和不能执行的规则相当复杂,但是可以说,用户模式的特权大大降低了。

现在,当人们谈论操作系统的内核时,他们指的是操作系统的代码部分,这些部分将以提升的特权在内核模式下运行。通常,内核作者出于安全原因尝试将内核保持尽可能小,因此不需要额外特权的代码就没有它们。

C编译器就是此类程序的一个示例-不需要内核模式提供的额外特权,因此它像大多数其他程序一样在用户模式下运行。

对于Linux,内核由两部分组成:内核的源代码和内核的已编译可执行文件。任何具有C编译器的机器都可以将内核从源代码编译为二进制映像。那么,问题是如何处理该二进制映像。

在新系统上安装Linux时,通常是从物理介质(例如CD DVD)或网络中安装预编译的二进制映像。BIOS将从媒体或网络中加载内核的引导程序(二进制映像),然后引导程序将内核的(二进制映像)安装到硬盘上。然后,当您重新启动时,BIOS从硬盘上加载内核的引导程序,而引导程序将内核加载到内存中,然后您就可以运行了。

如果您想重新编译自己的内核,那会有些棘手,但是可以做到。


5

首先是哪一个?鸡还是鸡蛋?

自恐龙时代以来,鸡蛋就已经存在了。

..有人通过说鸡实际上是伟大的野兽的后代来混淆一切。长话短说:技术(Egg)在当前产品(Chicken)之前就已经存在

您需要一个内核来构建内核,即您要一个内核与另一个内核。

第一个内核可以是任何您想要的内核(最好是可以创建所需最终产品^ __ ^的明智内核

Bran内核开发的本教程教您开发和构建较小的内核,然后可以使用您选择的虚拟机进行测试。

含义:您在某个地方编写和编译内核,然后在空的(无OS)虚拟机上读取它。

在这些Linux安装中发生的事情遵循相同的想法,但又增加了复杂性。


5

并不是乌龟一直走下去。就像您说的那样,您无法在运行该操作系统的系统上编译从未编译过的操作系统。同样,至少必须在另一个编译器上完成一个编译器的第一个构建(如果最初构建还不能编译自己的源代码,通常也需要一些后续构建)。

我认为最早的Linux内核是在Minix盒上编译的,尽管我不确定。GCC当时可用。许多操作系统的早期目标之一就是运行足够好的编译器以编译自己的源代码。更进一步,几乎可以肯定,第一个编译器是用汇编语言编写的。第一批汇编程序是由那些不得不用原始机器代码编写的穷人编写的。

您可能要签出Linux From Scratch项目。实际上,您在书中构建了两个系统:“临时系统”建立在您自己没有构建的系统上,然后构建“ LFS系统”在您临时系统上建立。本书的编写方式实际上是在另一个Linux机器上构建临时系统,但从理论上讲,您可以对其进行修改以在完全不同的OS上构建临时系统。


1

如果我正确理解您的问题。如今,内核不会“自行编译”。如今,大多数Linux发行版都通过linux live cd提供系统安装。内核从CD加载到内存中,并像通常安装到磁盘一样正常运行。在系统上启动并运行linux环境后,只需将必要的文件提交到磁盘即可。

如果您正在谈论引导问题;dmckee总结起来非常不错。

只是提供了另一种可能性 ...

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.