Linux内核如何编译自己?

时间:2009-01-30 03:22:55

标签: c linux compiler-construction

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

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

  1. 内核是用C语言编写的,但是在没有安装编译器的情况下如何编译内核?
  2. 如果在编译内核之前在我的机器上安装了C编译器,那么如何在没有安装编译器的情况下编译编译器本身?
  3. 我感到非常困惑,感谢您的回应。

7 个答案:

答案 0 :(得分:207)

你的Linux机器的第一轮二进制文件是在其他Linux机器上构建的(可能)。

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

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

...

推得足够远,您会发现使用更原始工具构建的编译器,这些工具又构建在除主机之外的机器上。

...

继续推动并找到计算机,以便通过机器前面板上的设置开关输入指令。

很酷的东西。

规则是“构建工具来构建工具来构建工具......”。非常像运行我们的物理环境的工具。也被称为“通过引导自我”。

答案 1 :(得分:33)

我认为你应该区分:

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

安装,v:连接,设置或准备使用[2]的内容。

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

现在,您的问题:

  
      
  1. 内核是用C语言编写的,但是在没有安装编译器的情况下如何编译内核?
  2.   

如果没有编译器就无法编译内核,但可以从已编译的二进制文件中安装

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

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

所以,你可以在不编译内核的情况下度过你的整个生活,因为你有别人编译它们。

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

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

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

现在,鸡肉和鸡蛋问题。第一个二进制文件是由其他人编译的......请参阅dmckee的优秀答案。

答案 2 :(得分:14)

描述这种现象的术语是bootstrapping,这是一个有趣的概念。如果你考虑嵌入式开发,很明显许多需要软件的设备,比如闹钟,微波炉,遥控器,都不足以编译自己的软件。实际上,这些类型的设备通常没有足够的资源来像编译器一样复杂地运行任何东西。

他们的软件是在台式机上开发的,然后在编译后复制。

如果您对此感兴趣,那么我首先想到的一篇文章是:Reflections on Trusting Trustpdf),这是一本经典且有趣的阅读。

答案 3 :(得分:11)

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

关于在用户模式和内核模式下哪些代码可以做什么和不能做什么的规则相当复杂,但足以说明,用户模式严重降低了特权。

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

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

在Linux的情况下,内核由两部分组成:内核的源代码和内核的编译可执行文件。任何带有C编译器的机器都可以将内核从源代码编译成二进制映像。那么,问题是如何处理二进制图像。

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

如果你想重新编译你自己的内核,这有点棘手,但可以做到。

答案 4 :(得分:5)

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

自恐龙时代以来,鸡蛋一直存在。

..有些人混淆了一切,说鸡实际上是大兽的后代......长话短说:技术(蛋)在当前产品(鸡)之前存在

你需要一个内核来构建一个内核,即你用另一个构建内核。

第一个内核可以是你想要的任何东西(最好是可以创造你想要的最终产品的合理的东西^ __ ^)

This tutorial from Bran's Kernel Development教您开发和构建一个小内核,然后您可以使用您选择的虚拟机进行测试。

含义:您在某处编写并编译内核,并在空(无操作系统)虚拟机上读取它。

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

答案 5 :(得分:5)

这不是乌龟一路下来。就像你说的那样,你无法在运行该操作系统的系统上编译以前从未编译过的操作系统。类似地,至少编译器的第一个版本必须在另一个编译器上完成(通常也是一些后续版本,如果第一个构建结果不能编译自己的源代码)。

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

您可能想查看Linux From Scratch项目。实际上,您在本书中构建了两个系统:一个构建在您自己未构建的系统上的“临时系统”,然后构建在临时系统上的“LFS系统”。本书目前的编写方式,您实际上是在另一个Linux机器上构建临时系统,但理论上您可以调整它以在完全不同的操作系统上构建临时系统。

答案 6 :(得分:1)

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

如果你在谈论自举问题; dmckee把它总结得相当不错。

只提供另一个可能性 ...